function hot_loop_allocs(f::F, args...) where {F}
# we want to test that f(args...) does not allocate
# when used in hot loops
# however a naive @allocated f(args...)
# will not be representative of what happens in an inner loop
# Instead it will sometimes box inputs/outputs
# and report too many allocations
# so we use Refs to minimize inputs and outputs
out_ref = Ref(f(args...))
arg_refs = map(Ref, args)
write_output_to_ref!(f, out_ref, arg_refs...)
out_ref = typeof(out_ref)() # erase out_ref so we can assert work was done later
# Avoid splatting args... which also results in undesired allocs
allocs = if length(arg_refs) == 1
r1, = arg_refs
@allocated write_output_to_ref!(f, out_ref, r1)
elseif length(arg_refs) == 2
r1,r2 = arg_refs
@allocated write_output_to_ref!(f, out_ref, r1, r2)
else
error("TODO too many args")
end
@assert out_ref[] == f(args...)
return allocs
end
Check out this code which presumably understands the Julia compiler better than I do:
https://github.com/JuliaObjects/ConstructionBase.jl/blob/master/test/runtests.jl#L427-L451