Skip to content

Commit c5e918c

Browse files
WIP log testsetup start/done and timings
1 parent 5f91402 commit c5e918c

File tree

3 files changed

+81
-40
lines changed

3 files changed

+81
-40
lines changed

src/ReTestItems.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -864,9 +864,12 @@ function runtestsetup(ts::TestSetup, ctx::TestContext; logs::Symbol)
864864
mod_expr = :(module $(gensym(ts.name)) end)
865865
# replace the module expr body with our @testsetup code
866866
mod_expr.args[3] = ts.code
867-
newmod = _redirect_logs(logs == :eager ? DEFAULT_STDOUT[] : ts.logstore[]) do
867+
log_testsetup_start(ts)
868+
newmod, stats = @timed_with_compilation _redirect_logs(logs == :eager ? DEFAULT_STDOUT[] : ts.logstore[]) do
868869
with_source_path(() -> Core.eval(Main, mod_expr), ts.file)
869870
end
871+
ts.stats[] = stats
872+
log_testsetup_done(ts)
870873
# add the new module to our TestSetupModules
871874
mods.modules[ts.name] = newmod
872875
return nameof(newmod)

src/log_capture.jl

+29-4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ function _print_scaled_one_dec(io, value, scale, label="")
5555
end
5656
print(io, label)
5757
end
58+
function print_time(io::IO, s::PerfStats)
59+
return print_time(
60+
io; s.elapsedtime, s.bytes, s.gctime, s.allocs, s.compile_time, s.recompile_time
61+
)
62+
end
5863
function print_time(io; elapsedtime, bytes=0, gctime=0, allocs=0, compile_time=0, recompile_time=0)
5964
_print_scaled_one_dec(io, elapsedtime, 1e9, " secs")
6065
if gctime > 0 || compile_time > 0
@@ -243,7 +248,7 @@ function _print_test_errors(report_iob, ts::DefaultTestSet, worker_info)
243248
return nothing
244249
end
245250

246-
function print_state(io, state, ti, ntestitems; color=:default)
251+
function print_state(io::IO, state::String, ti::TestItem, ntestitems; color=:default)
247252
interactive = parse(Bool, get(ENV, "RETESTITEMS_INTERACTIVE", string(Base.isinteractive())))
248253
print(io, format(now(), "HH:MM:SS | "))
249254
!interactive && print(io, _mem_watermark())
@@ -256,6 +261,13 @@ function print_state(io, state, ti, ntestitems; color=:default)
256261
end
257262
print(io, " test item $(repr(ti.name)) ")
258263
end
264+
function print_state(io::IO, state::String, ts::TestSetup)
265+
interactive = parse(Bool, get(ENV, "RETESTITEMS_INTERACTIVE", string(Base.isinteractive())))
266+
print(io, format(now(), "HH:MM:SS | "))
267+
!interactive && print(io, _mem_watermark())
268+
printstyled(io, rpad(uppercase(state), 5))
269+
print(io, " test setup $(ts.name) ")
270+
end
259271

260272
function print_file_info(io, ti)
261273
print(io, "at ")
@@ -270,20 +282,33 @@ function log_testitem_skipped(ti::TestItem, ntestitems=0)
270282
write(DEFAULT_STDOUT[], take!(io.io))
271283
end
272284

273-
# Marks the start of each test item
274285
function log_testitem_start(ti::TestItem, ntestitems=0)
275286
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
276287
print_state(io, "START", ti, ntestitems)
277288
print_file_info(io, ti)
278289
println(io)
279290
write(DEFAULT_STDOUT[], take!(io.io))
280291
end
292+
function log_testsetup_start(ts::TestSetup)
293+
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
294+
print_state(io, "START", ts)
295+
print_file_info(io, ts)
296+
println(io)
297+
write(DEFAULT_STDOUT[], take!(io.io))
298+
end
281299

282300
function log_testitem_done(ti::TestItem, ntestitems=0)
283301
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
284302
print_state(io, "DONE", ti, ntestitems)
285-
x = last(ti.stats) # always print stats for most recent run
286-
print_time(io; x.elapsedtime, x.bytes, x.gctime, x.allocs, x.compile_time, x.recompile_time)
303+
stats = last(ti.stats) # always print stats for most recent run
304+
print_time(io, stats)
305+
println(io)
306+
write(DEFAULT_STDOUT[], take!(io.io))
307+
end
308+
function log_testsetup_done(ts::TestSetup, ntestitems=0)
309+
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
310+
print_state(io, "DONE", ts)
311+
print_time(io, ts.stats[])
287312
println(io)
288313
write(DEFAULT_STDOUT[], take!(io.io))
289314
end

src/macros.jl

+48-35
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,46 @@
11
gettls(k, d) = get(task_local_storage(), k, d)
22

33
###
4-
### testsetup
4+
### PerfStats
5+
###
6+
7+
Base.@kwdef struct PerfStats
8+
elapsedtime::UInt=0
9+
bytes::Int=0
10+
gctime::Int=0
11+
allocs::Int=0
12+
compile_time::UInt=0
13+
recompile_time::UInt=0
14+
end
15+
16+
# Adapted from Base.@time
17+
macro timed_with_compilation(ex)
18+
quote
19+
Base.Experimental.@force_compile
20+
local stats = Base.gc_num()
21+
local elapsedtime = Base.time_ns()
22+
Base.cumulative_compile_timing(true)
23+
local compile_elapsedtimes = Base.cumulative_compile_time_ns()
24+
local val = Base.@__tryfinally($(esc(ex)),
25+
(elapsedtime = Base.time_ns() - elapsedtime;
26+
Base.cumulative_compile_timing(false);
27+
compile_elapsedtimes = Base.cumulative_compile_time_ns() .- compile_elapsedtimes)
28+
)
29+
local diff = Base.GC_Diff(Base.gc_num(), stats)
30+
local out = PerfStats(;
31+
elapsedtime, bytes=diff.allocd, gctime=diff.total_time, allocs=Base.gc_alloc_count(diff),
32+
compile_time=first(compile_elapsedtimes), recompile_time=last(compile_elapsedtimes)
33+
)
34+
val, out
35+
end
36+
end
37+
38+
###
39+
### TestSetup
540
###
641

742
"""
8-
TestSetup(name, code)
43+
TestSetup
944
1045
A module that a `TestItem` can require to be run before that `TestItem` is run.
1146
Used for declaring code that multiple `TestItem`s rely on.
@@ -21,6 +56,10 @@ struct TestSetup
2156
# the test setup. This IO object is only for writing on the worker. The coordinator needs
2257
# to open the file when it needs to read from it.
2358
logstore::Base.RefValue{IOStream} # Populated and only safe to use on the worker
59+
stats::Base.RefValue{PerfStats} # populated when the test setup is finished running
60+
end
61+
function TestSetup(name::Symbol, code, file::String, line::Int, project_root::String)
62+
return TestSetup(name, code, file, line, project_root, Ref{IOStream}(), Ref{PerfStats}())
2463
end
2564

2665
"""
@@ -53,46 +92,20 @@ macro testsetup(mod)
5392
name isa Symbol || error("`@testsetup module` expects a valid module name")
5493
nm = QuoteNode(name)
5594
q = QuoteNode(code)
95+
_source = QuoteNode(__source__)
5696
esc(quote
57-
$store_test_setup($TestSetup($nm, $q, $(String(__source__.file)), $(__source__.line), $gettls(:__RE_TEST_PROJECT__, "."), Ref{IOStream}()))
97+
$store_test_setup(
98+
$TestSetup(
99+
$nm, $q, $String($_source.file), $_source.line, $gettls(:__RE_TEST_PROJECT__, "."),
100+
)
101+
)
58102
end)
59103
end
60104

61105
###
62-
### testitem
106+
### TestItem
63107
###
64108

65-
Base.@kwdef struct PerfStats
66-
elapsedtime::UInt=0
67-
bytes::Int=0
68-
gctime::Int=0
69-
allocs::Int=0
70-
compile_time::UInt=0
71-
recompile_time::UInt=0
72-
end
73-
74-
# Adapted from Base.@time
75-
macro timed_with_compilation(ex)
76-
quote
77-
Base.Experimental.@force_compile
78-
local stats = Base.gc_num()
79-
local elapsedtime = Base.time_ns()
80-
Base.cumulative_compile_timing(true)
81-
local compile_elapsedtimes = Base.cumulative_compile_time_ns()
82-
local val = Base.@__tryfinally($(esc(ex)),
83-
(elapsedtime = Base.time_ns() - elapsedtime;
84-
Base.cumulative_compile_timing(false);
85-
compile_elapsedtimes = Base.cumulative_compile_time_ns() .- compile_elapsedtimes)
86-
)
87-
local diff = Base.GC_Diff(Base.gc_num(), stats)
88-
local out = PerfStats(;
89-
elapsedtime, bytes=diff.allocd, gctime=diff.total_time, allocs=Base.gc_alloc_count(diff),
90-
compile_time=first(compile_elapsedtimes), recompile_time=last(compile_elapsedtimes)
91-
)
92-
val, out
93-
end
94-
end
95-
96109
mutable struct ScheduledForEvaluation
97110
@atomic value::Bool
98111
end

0 commit comments

Comments
 (0)