Skip to content

Commit 1d311fd

Browse files
WIP log testsetup start/done and timings
1 parent d782502 commit 1d311fd

File tree

3 files changed

+81
-40
lines changed

3 files changed

+81
-40
lines changed

src/ReTestItems.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,9 +856,12 @@ function runtestsetup(ts::TestSetup, ctx::TestContext; logs::Symbol)
856856
mod_expr = :(module $(gensym(ts.name)) end)
857857
# replace the module expr body with our @testsetup code
858858
mod_expr.args[3] = ts.code
859-
newmod = _redirect_logs(logs == :eager ? DEFAULT_STDOUT[] : ts.logstore[]) do
859+
log_testsetup_start(ts)
860+
newmod, stats = @timed_with_compilation _redirect_logs(logs == :eager ? DEFAULT_STDOUT[] : ts.logstore[]) do
860861
with_source_path(() -> Core.eval(Main, mod_expr), ts.file)
861862
end
863+
ts.stats[] = stats
864+
log_testsetup_done(ts)
862865
# add the new module to our TestSetupModules
863866
mods.modules[ts.name] = newmod
864867
return nameof(newmod)

src/log_capture.jl

Lines changed: 29 additions & 4 deletions
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
@@ -241,7 +246,7 @@ function _print_test_errors(report_iob, ts::DefaultTestSet, worker_info)
241246
return nothing
242247
end
243248

244-
function print_state(io, state, ti, ntestitems; color=:default)
249+
function print_state(io::IO, state::String, ti::TestItem, ntestitems; color=:default)
245250
interactive = parse(Bool, get(ENV, "RETESTITEMS_INTERACTIVE", string(Base.isinteractive())))
246251
print(io, format(now(), "HH:MM:SS | "))
247252
!interactive && print(io, _mem_watermark())
@@ -254,6 +259,13 @@ function print_state(io, state, ti, ntestitems; color=:default)
254259
end
255260
print(io, " test item $(repr(ti.name)) ")
256261
end
262+
function print_state(io::IO, state::String, ts::TestSetup)
263+
interactive = parse(Bool, get(ENV, "RETESTITEMS_INTERACTIVE", string(Base.isinteractive())))
264+
print(io, format(now(), "HH:MM:SS | "))
265+
!interactive && print(io, _mem_watermark())
266+
printstyled(io, rpad(uppercase(state), 5))
267+
print(io, " test setup $(ts.name) ")
268+
end
257269

258270
function print_file_info(io, ti)
259271
print(io, "at ")
@@ -268,20 +280,33 @@ function log_testitem_skipped(ti::TestItem, ntestitems=0)
268280
write(DEFAULT_STDOUT[], take!(io.io))
269281
end
270282

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

280298
function log_testitem_done(ti::TestItem, ntestitems=0)
281299
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
282300
print_state(io, "DONE", ti, ntestitems)
283-
x = last(ti.stats) # always print stats for most recent run
284-
print_time(io; x.elapsedtime, x.bytes, x.gctime, x.allocs, x.compile_time, x.recompile_time)
301+
stats = last(ti.stats) # always print stats for most recent run
302+
print_time(io, stats)
303+
println(io)
304+
write(DEFAULT_STDOUT[], take!(io.io))
305+
end
306+
function log_testsetup_done(ts::TestSetup, ntestitems=0)
307+
io = IOContext(IOBuffer(), :color => get(DEFAULT_STDOUT[], :color, false)::Bool)
308+
print_state(io, "DONE", ts)
309+
print_time(io, ts.stats[])
285310
println(io)
286311
write(DEFAULT_STDOUT[], take!(io.io))
287312
end

src/macros.jl

Lines changed: 48 additions & 35 deletions
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)