-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter testitems from AST before eval
to reduce latency
#170
Conversation
FWIW, here is my very hacky implementation that skips eval , which does show a very significant perf improvement (but it does cheat by skipping over |
ooo very interesting -- i think the key is filtering the testitems out with julia> code1 = Union{Expr,Nothing}[:() for _ in 1:100_000];
julia> code2 = Union{Expr,Nothing}[nothing for _ in 1:100_000];
julia> @time for c in code1
Core.eval(Main, c)
end
3.848924 seconds (3.60 M allocations: 164.779 MiB, 0.62% gc time)
julia> @time for c in code2
Core.eval(Main, c)
end
0.015101 seconds (298.98 k allocations: 4.562 MiB) i also like the |
79d7595
to
ab2c128
Compare
This reverts commit a61eb98.
ab2c128
to
481010d
Compare
eval
eval
to reduce latency
I can't seem to replicate the 1 second speedup on RAICode:/ @btime runtests("test", name="aalkbjlhkbkhjvkhfcjgfca")
# PR: 1.533 s (6831030 allocations: 431.75 MiB)
# 1.24.0: 1.633 s (8192533 allocations: 497.06 MiB) It seems that the remaining overhead is coming from # diff: 301.330 ms (3016961 allocations: 240.58 MiB) What do you think? Is it worth special-casing test-rel like this? What would the alternative be? |
# custom function that doesn't call `Core.eval(M, expr)` if `expr === nothing`, but | ||
# using `Base.include` means we benefit from improvements made upstream rather than | ||
# having to maintain our own version of that code. | ||
function filter_testitem(f, expr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got confused a little because there are two points at which we filter test items -- here at the AST level and then later in the FilteredVector
level when we filter on the eval
d TestItem
. Let's maybe explain here, the things that need to be expanded, like:
@testitem "name with interpolation $(VERSION)" begin ... end
get filtered later and where? Because I think I'll forget how things work again:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooo, name with interpolation is interesting... i've never thought of us as (officially) supporting that.
i always thought we'd (one day) require files only have @testitem
and @testsetup
calls at the top-level, and that name
and tags
must be a static
But yes, you're quite right, for things that need to be expanded before filtering (@test_rel
, @eval ...
) we have to filter later in the FilteredVector
, which is why (one day) i'd like us to not support those things at all and do all filter on the AST. Will add more comments explaining this.
i've been reluctant to special-case BUT the compromise instead has to be allow any top-level macro-call (so as to allow @eval begin
num_groups = 32
for group_id in 1:num_groups
eval(quote
@testitem "MapOperator all natives - group $($group_id)" begin
end
)
end
end So, currently in this PR i stick with the (bad) status quo where we support arbitrary macrocalls at the top-level (assuming the create But we could instead disallow all macro-calls except idk what's best. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is great! A bunch of folks should get a nice latency reduction out of this:)
For RAI though, I think the transition to this new version of ReTestItems will be slightly challenging since we now disallow top-level @eval
and I think the macro nesting with @test_rel
cause some issues for the filtering logic, e.g. now I get these errors from @test_rel
:
`tags` keyword must be passed a collection of `Symbol`s, got: $(Expr(:escape, :([:ring2, :integration])))
(I've tweaked the error message a bit to see what we got for tags
).
Lastly, I think for RAI specifically, a good chunk of the latency reduction is still on the table, since currently, we eval all of the @test_rel
s. It would be great if we could also try to extract the name and tags from these (many of them do have names and tags so we we should be able to skip eval often), but that can wait for a later PR.
i'll make a PR to update the codebase to remove
agreed 👍 -- just want to land that in a follow-up PR as you say 😁
this bit i didn't quite follow -- is it separate from the usage of |
found what was wrong -- thanks for the pointer! |
The aim is to make interactive use of
runtests()
much snappier, specifically to improve time-to-first-test when filtering to specific testitems.With this PR we now remove any
@testitem
s that aren't requested by the user (because the user passedname
and/ortags
and/or their ownshouldrun
function) from the AST before evaluating the code and constructingTestItem
objects. Filtering the ASTshould be faster, but so far it looks like about that sameis much faster:Here are timings on a synthetic benchmark which calls
runtests(...)
and filters out all the tests, for a large number of test-items across many test filesNow
Before (v1.25):
benchmark code
Running
$ julia --proj bench/filtering.jl
with the file:RAI use-case
For the RAI test suite... this shaves off 1 second (about 40% of the time) for all directories where filtering can be done exclusively on the AST:
1.517397 seconds
2.576764 seconds
(running
runtests(dirs_with_unit_tests...; name="nopenope", tags=:nope)
to filter out all testitems, i.e. run no tests, from these directories)And for all directories (including those which may require
eval
ing the files):10.974462 seconds
16.653225 seconds
(running
runtests(; name="nopenope", tags=:nope)
to filter out all testitems, i.e. run no tests)joint work with @Drvi
xref #41