In writing my code, I often find that I wish to test if a certain function, say f
, can be made quicker. One way of doing this is to find a place within my code where the function gets used and run f
and some f_quick
based on the data in that place of the code, where f_quick
is hopefully is quicker. This effectively boils down to running RunCheck(N)
in the MWE below.
However, this means Iβll need to manually track occurrences of f
in my code and modifying the code there to run the check. A trick Iβm using now is the following, which Iβll write up for a function named g
to keep the MWE sensible. I rename the original function g
to g_slow
and the potential new version to g_quick
. I then write a function g
that runs the checks automatically (and either errors on the first occurrence (non-commented version) or continues if the outputs of g_slow and g_quick agree (commented version)).
This works reasonably well for development, but I find myself in the situation where I want to use this workflow for various functions g
, each of which may have different numbers of arguments. So, I was wondering if there is a meta-programming way that, as soon as it finds a function name that ends in _slow
, e.g. g_slow
, writes a function g
that accepts the same inputs and runs the checks/benchmarks I wish.
I hope the below MWE indicates what I wish:
using BenchmarkTools, Random, Distributions
Random.seed!(42)
# Suppose I wrote this simple function and use it throughout my code
f(x, y) = all(x .< y)
# I may think that the following is quicker
f_quick(x, y) = all(xi < yi for (xi, yi) in zip(x, y))
# Manual code for checking:
function RunCheck(N)
x = rand(N)
y = rand(N)
display(f(x, y) == f_quick(x, y)) # To be certain of this, you'd need to repeat the sampling, of course
display(@benchmark f($x, $y))
display(@benchmark f_quick($x, $y))
return nothing
end
# Instead, I wish to check the performance of the two functions "in context" of my code
# g(x,y) = all(x .< y) # This is the function I currently use. I rename it to g_slow and write a new function g_quick
g_slow(x, y) = all(x .< y)
g_quick(x, y) = all(xi < yi for (xi, yi) in zip(x, y))
# Now, we define a new g:
function g(x,y)
display(g_slow(x, y) == g_quick(x, y))
display(@benchmark g_slow($x, $y))
display(@benchmark g_quick($x, $y))
error()
end
#or a version that can be tried at every occurence
function g(x,y)
x_slow = g_slow(x, y)
x_quick = g_quick(x, y)
display(x_slow == x_quick)
display("Testing: ")
display(@benchmark g_slow($x, $y))
display(@benchmark g_quick($x, $y))
if x_slow == x_quick
return x_slow
else
display(x_slow)
display(x_quick)
error("Mismatch!")
end
end
function CheckInCode(N)
x = rand(N)
y = rand(N)
z = g(x, y)
return z
end
RunCheck(1000)
CheckInCode(1000)
gives
true
BenchmarkTools.Trial: 10000 samples with 506 evaluations.
Range (min β¦ max): 219.121 ns β¦ 5.485 ΞΌs β GC (min β¦ max): 0.00% β¦ 94.74%
Time (median): 226.862 ns β GC (median): 0.00%
Time (mean Β± Ο): 242.263 ns Β± 132.021 ns β GC (mean Β± Ο): 4.77% Β± 7.98%
β
βββββ
βββββββ β β
βββββββββββββββββββββββββββ
β
β
β
β
βββ
β
ββββββββββββββββββββββββββ β
219 ns Histogram: log(frequency) by time 388 ns <
Memory estimate: 224 bytes, allocs estimate: 3.
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min β¦ max): 2.791 ns β¦ 27.416 ns β GC (min β¦ max): 0.00% β¦ 0.00%
Time (median): 2.917 ns β GC (median): 0.00%
Time (mean Β± Ο): 2.944 ns Β± 0.383 ns β GC (mean Β± Ο): 0.00% Β± 0.00%
β β β β β β β
ββββββββββββββββββββββ
ββ
ββββ
βββββββββββββββββββββββ
ββββ
βββ β
2.79 ns Histogram: log(frequency) by time 4.04 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
true
"Testing: "
BenchmarkTools.Trial: 10000 samples with 501 evaluations.
Range (min β¦ max): 221.058 ns β¦ 8.514 ΞΌs β GC (min β¦ max): 0.00% β¦ 96.85%
Time (median): 228.958 ns β GC (median): 0.00%
Time (mean Β± Ο): 241.355 ns Β± 150.085 ns β GC (mean Β± Ο): 3.70% Β± 6.04%
ββ
ββββββββββββ β
ββββββββββββββββββββββββββββββ
βββ
ββββββββββββββ
ββββ
β
ββ
β
βββ
βββ β
221 ns Histogram: log(frequency) by time 295 ns <
Memory estimate: 224 bytes, allocs estimate: 3.
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min β¦ max): 2.250 ns β¦ 42.750 ns β GC (min β¦ max): 0.00% β¦ 0.00%
Time (median): 2.375 ns β GC (median): 0.00%
Time (mean Β± Ο): 2.430 ns Β± 0.907 ns β GC (mean Β± Ο): 0.00% Β± 0.00%
β β β β β
β β β β β β
ββββββββββββββββββββββββββββββββββββββ
βββββ
βββββββββββββββ β
2.25 ns Histogram: log(frequency) by time 3.33 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
false