Skip to content

Commit a8e48df

Browse files
authored
improve load performance (#200)
Reduce unnecessary specialization, so we only compile the benchmark itself
1 parent 32fdfbd commit a8e48df

File tree

2 files changed

+40
-49
lines changed

2 files changed

+40
-49
lines changed

src/execution.jl

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ gcscrub() = (GC.gc(); GC.gc(); GC.gc(); GC.gc())
77
# Benchmark #
88
#############
99

10-
mutable struct Benchmark{id}
10+
mutable struct Benchmark
11+
samplefunc
1112
params::Parameters
1213
end
1314

@@ -87,9 +88,24 @@ end
8788
# Note that trials executed via `run` and `lineartrial` are always executed at top-level
8889
# scope, in order to allow transfer of locally-scoped variables into benchmark scope.
8990

90-
# these stubs get overloaded by @benchmarkable
91-
function sample end
92-
function _run end
91+
function _run(b::Benchmark, p::Parameters; verbose = false, pad = "", kwargs...)
92+
params = Parameters(p; kwargs...)
93+
@assert params.seconds > 0.0 "time limit must be greater than 0.0"
94+
params.gctrial && gcscrub()
95+
start_time = Base.time()
96+
trial = Trial(params)
97+
params.gcsample && gcscrub()
98+
s = b.samplefunc(params)
99+
push!(trial, s[1:end-1]...)
100+
return_val = s[end]
101+
iters = 2
102+
while (Base.time() - start_time) < params.seconds && iters params.samples
103+
params.gcsample && gcscrub()
104+
push!(trial, b.samplefunc(params)[1:end-1]...)
105+
iters += 1
106+
end
107+
return sort!(trial), return_val
108+
end
93109

94110
Base.run(b::Benchmark, p::Parameters = b.params; progressid=nothing, nleaves=NaN, ndone=NaN, kwargs...) =
95111
run_result(b, p; kwargs...)[1]
@@ -130,7 +146,7 @@ function _lineartrial(b::Benchmark, p::Parameters = b.params; maxevals = RESOLUT
130146
for evals in eachindex(estimates)
131147
params.gcsample && gcscrub()
132148
params.evals = evals
133-
estimates[evals] = first(sample(b, params))
149+
estimates[evals] = first(b.samplefunc(params))
134150
completed += 1
135151
((time() - start_time) > params.seconds) && break
136152
end
@@ -216,6 +232,7 @@ end
216232
#############################
217233

218234
function prunekwargs(args...)
235+
@nospecialize
219236
firstarg = first(args)
220237
if isa(firstarg, Expr) && firstarg.head == :parameters
221238
return prunekwargs(drop(args, 1)..., firstarg.args...)
@@ -291,6 +308,7 @@ macro benchmark(args...)
291308
end
292309

293310
function benchmarkable_parts(args)
311+
@nospecialize
294312
core, params = prunekwargs(args...)
295313

296314
# extract setup/teardown if present, removing them from the original expression
@@ -321,22 +339,23 @@ end
321339

322340
macro benchmarkable(args...)
323341
core, setup, teardown, params = benchmarkable_parts(args)
342+
map!(esc, params, params)
324343

325344
# extract any variable bindings shared between the core and setup expressions
326345
setup_vars = isa(setup, Expr) ? collectvars(setup) : []
327346
core_vars = isa(core, Expr) ? collectvars(core) : []
328347
out_vars = filter(var -> var in setup_vars, core_vars)
329348

330349
# generate the benchmark definition
331-
return esc(quote
332-
$BenchmarkTools.generate_benchmark_definition($__module__,
333-
$(Expr(:quote, out_vars)),
334-
$(Expr(:quote, setup_vars)),
335-
$(Expr(:quote, core)),
336-
$(Expr(:quote, setup)),
337-
$(Expr(:quote, teardown)),
338-
$Parameters($(params...)))
339-
end)
350+
return quote
351+
generate_benchmark_definition($__module__,
352+
$(Expr(:quote, out_vars)),
353+
$(Expr(:quote, setup_vars)),
354+
$(esc(Expr(:quote, core))),
355+
$(esc(Expr(:quote, setup))),
356+
$(esc(Expr(:quote, teardown))),
357+
Parameters($(params...)))
358+
end
340359
end
341360

342361
# `eval` an expression that forcibly defines the specified benchmark at
@@ -347,7 +366,7 @@ end
347366
# possible for them to conflict with names used in the setup or teardown expressions.
348367
# A more robust solution would be preferable.
349368
function generate_benchmark_definition(eval_module, out_vars, setup_vars, core, setup, teardown, params)
350-
id = Expr(:quote, gensym("benchmark"))
369+
@nospecialize
351370
corefunc = gensym("core")
352371
samplefunc = gensym("sample")
353372
type_vars = [gensym() for i in 1:length(setup_vars)]
@@ -389,31 +408,7 @@ function generate_benchmark_definition(eval_module, out_vars, setup_vars, core,
389408
__evals))
390409
return __time, __gctime, __memory, __allocs, __return_val
391410
end
392-
function $BenchmarkTools.sample(b::$BenchmarkTools.Benchmark{$(id)},
393-
p::$BenchmarkTools.Parameters = b.params)
394-
return $(samplefunc)(p)
395-
end
396-
function $BenchmarkTools._run(b::$BenchmarkTools.Benchmark{$(id)},
397-
p::$BenchmarkTools.Parameters;
398-
verbose = false, pad = "", kwargs...)
399-
params = $BenchmarkTools.Parameters(p; kwargs...)
400-
@assert params.seconds > 0.0 "time limit must be greater than 0.0"
401-
params.gctrial && $BenchmarkTools.gcscrub()
402-
start_time = Base.time()
403-
trial = $BenchmarkTools.Trial(params)
404-
params.gcsample && $BenchmarkTools.gcscrub()
405-
s = $(samplefunc)(params)
406-
push!(trial, s[1:end-1]...)
407-
return_val = s[end]
408-
iters = 2
409-
while (Base.time() - start_time) < params.seconds && iters params.samples
410-
params.gcsample && $BenchmarkTools.gcscrub()
411-
push!(trial, $(samplefunc)(params)[1:end-1]...)
412-
iters += 1
413-
end
414-
return sort!(trial), return_val
415-
end
416-
$BenchmarkTools.Benchmark{$(id)}($(params))
411+
$BenchmarkTools.Benchmark($(samplefunc), $(params))
417412
end)
418413
end
419414

src/groups.jl

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,13 @@ Base.iterate(group::BenchmarkGroup, i=1) = iterate(group.data, i)
4949
andexpr(a, b) = :($a && $b)
5050
andreduce(preds) = reduce(andexpr, preds)
5151

52-
@generated function mapvals!(f, dest::BenchmarkGroup, srcs::BenchmarkGroup...)
53-
haskeys = andreduce([:(haskey(srcs[$i], k)) for i in 1:length(srcs)])
54-
getinds = [:(srcs[$i][k]) for i in 1:length(srcs)]
55-
return quote
56-
for k in keys(first(srcs))
57-
if $(haskeys)
58-
dest[k] = f($(getinds...))
59-
end
52+
function mapvals!(f, dest::BenchmarkGroup, srcs::BenchmarkGroup...)
53+
for k in keys(first(srcs))
54+
if all(s -> haskey(s, k), srcs)
55+
dest[k] = f((s[k] for s in srcs)...)
6056
end
61-
return dest
6257
end
58+
return dest
6359
end
6460

6561
mapvals!(f, group::BenchmarkGroup) = mapvals!(f, similar(group), group)

0 commit comments

Comments
 (0)