From ecf83670eaf74127c8803ec7b3bd2b0933450edf Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Wed, 27 Nov 2024 15:24:16 -0600 Subject: [PATCH 1/2] Tell the compiler about the value of the input to f if it is a type (and test) --- src/benchmarking.jl | 30 +++++++++++++++++++++++++++--- test/runtests.jl | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/benchmarking.jl b/src/benchmarking.jl index 98970761..a79d54f3 100644 --- a/src/benchmarking.jl +++ b/src/benchmarking.jl @@ -121,7 +121,7 @@ function _benchmark_2(args1, setup, teardown, gc::Bool, evals::Int, warmup::Bool rp = ntuple(N) do i old_gc = gc || GC.enable(false) sample, ti, args3 = try - _benchmark_3(fs[p[i]], args2, evals, warmup) + _benchmark_3(fs[p[i]], evals, warmup, args2...) finally gc || GC.enable(old_gc) end @@ -134,7 +134,8 @@ function _benchmark_2(args1, setup, teardown, gc::Bool, evals::Int, warmup::Bool end _div(a, b) = a == b == 0 ? zero(a/b) : a/b -function _benchmark_3(f::F, args::A, evals::Int, warmup::Bool) where {F, A} +function _benchmark_3(f::F, evals::Int, warmup::Bool, args...) where {F} + gcstats = Base.gc_num() cumulative_compile_timing(true) gcstats0 = Base.gc_num() ctime, time0, time1, res, gcstats1 = try @@ -157,4 +158,27 @@ function _benchmark_3(f::F, args::A, evals::Int, warmup::Bool) where {F, A} rtime = time1 - time0 gcdiff = Base.GC_Diff(gcstats1, gcstats0) Sample(evals, 1e-9rtime/evals, Base.gc_alloc_count(gcdiff)/evals, gcdiff.allocd/evals, _div(gcdiff.total_time,rtime), _div(ctime[1],rtime), _div(ctime[2],ctime[1]), warmup), time1, res -end \ No newline at end of file +end +function _benchmark_3(f::F, evals::Int, warmup::Bool, arg::Type{T}) where {F, T} + gcstats = Base.gc_num() + cumulative_compile_timing(true) + ctime, time0, time1, res = try + ctime = cumulative_compile_time_ns() + time0 = time_ns() + res = @static VERSION >= v"1.8" ? @noinline(f(arg)) : f(arg) + donotdelete(res) + for _ in 2:evals + x = @static VERSION >= v"1.8" ? @noinline(f(arg)) : f(arg) + donotdelete(x) + end + time1 = time_ns() + ctime = cumulative_compile_time_ns() .- ctime + + ctime, time0, time1, res + finally + cumulative_compile_timing(false) + end + rtime = time1 - time0 + gcdiff = Base.GC_Diff(Base.gc_num(), gcstats) + Sample(evals, 1e-9rtime/evals, Base.gc_alloc_count(gcdiff)/evals, gcdiff.allocd/evals, _div(gcdiff.total_time,rtime), _div(ctime[1],rtime), _div(ctime[2],ctime[1]), warmup), time1, res +end diff --git a/test/runtests.jl b/test/runtests.jl index 6d0ea1af..d20740de 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -443,6 +443,10 @@ else x = 1 @test isinteger((@b hash(x) seconds=.001).allocs) end + + @testset "Issue #107, specialization" begin + @test (@b Int rand).allocs == 0 + end end @testset "Statistics Extension" begin From b88f1452ae816cce7115e54edbcc38ff361ffae1 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Wed, 27 Nov 2024 15:29:37 -0600 Subject: [PATCH 2/2] Replace duplication with metaprogramming --- src/benchmarking.jl | 69 ++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/src/benchmarking.jl b/src/benchmarking.jl index a79d54f3..8b05f793 100644 --- a/src/benchmarking.jl +++ b/src/benchmarking.jl @@ -134,51 +134,32 @@ function _benchmark_2(args1, setup, teardown, gc::Bool, evals::Int, warmup::Bool end _div(a, b) = a == b == 0 ? zero(a/b) : a/b -function _benchmark_3(f::F, evals::Int, warmup::Bool, args...) where {F} - gcstats = Base.gc_num() - cumulative_compile_timing(true) - gcstats0 = Base.gc_num() - ctime, time0, time1, res, gcstats1 = try - ctime = cumulative_compile_time_ns() - time0 = time_ns() - res = @static VERSION >= v"1.8" ? @noinline(f(args...)) : f(args...) - donotdelete(res) - for _ in 2:evals - x = @static VERSION >= v"1.8" ? @noinline(f(args...)) : f(args...) - donotdelete(x) - end - time1 = time_ns() - ctime = cumulative_compile_time_ns() .- ctime - gcstats1 = Base.gc_num() +let body(args) = + quote + gcstats = Base.gc_num() + cumulative_compile_timing(true) + gcstats0 = Base.gc_num() + ctime, time0, time1, res, gcstats1 = try + ctime = cumulative_compile_time_ns() + time0 = time_ns() + res = @static VERSION >= v"1.8" ? @noinline(f($args)) : f($args) + donotdelete(res) + for _ in 2:evals + x = @static VERSION >= v"1.8" ? @noinline(f($args)) : f($args) + donotdelete(x) + end + time1 = time_ns() + ctime = cumulative_compile_time_ns() .- ctime + gcstats1 = Base.gc_num() - ctime, time0, time1, res, gcstats1 - finally - cumulative_compile_timing(false) - end - rtime = time1 - time0 - gcdiff = Base.GC_Diff(gcstats1, gcstats0) - Sample(evals, 1e-9rtime/evals, Base.gc_alloc_count(gcdiff)/evals, gcdiff.allocd/evals, _div(gcdiff.total_time,rtime), _div(ctime[1],rtime), _div(ctime[2],ctime[1]), warmup), time1, res -end -function _benchmark_3(f::F, evals::Int, warmup::Bool, arg::Type{T}) where {F, T} - gcstats = Base.gc_num() - cumulative_compile_timing(true) - ctime, time0, time1, res = try - ctime = cumulative_compile_time_ns() - time0 = time_ns() - res = @static VERSION >= v"1.8" ? @noinline(f(arg)) : f(arg) - donotdelete(res) - for _ in 2:evals - x = @static VERSION >= v"1.8" ? @noinline(f(arg)) : f(arg) - donotdelete(x) + ctime, time0, time1, res, gcstats1 + finally + cumulative_compile_timing(false) end - time1 = time_ns() - ctime = cumulative_compile_time_ns() .- ctime - - ctime, time0, time1, res - finally - cumulative_compile_timing(false) + rtime = time1 - time0 + gcdiff = Base.GC_Diff(gcstats1, gcstats0) + Sample(evals, 1e-9rtime/evals, Base.gc_alloc_count(gcdiff)/evals, gcdiff.allocd/evals, _div(gcdiff.total_time,rtime), _div(ctime[1],rtime), _div(ctime[2],ctime[1]), warmup), time1, res end - rtime = time1 - time0 - gcdiff = Base.GC_Diff(Base.gc_num(), gcstats) - Sample(evals, 1e-9rtime/evals, Base.gc_alloc_count(gcdiff)/evals, gcdiff.allocd/evals, _div(gcdiff.total_time,rtime), _div(ctime[1],rtime), _div(ctime[2],ctime[1]), warmup), time1, res + @eval _benchmark_3(f::F, evals::Int, warmup::Bool, args...) where F = $(body(:(args...))) + @eval _benchmark_3(f::F, evals::Int, warmup::Bool, arg::Type{T}) where {F, T} = $(body(:arg)) end