The solution is rather simple: add @inline to test_calc. Then allocation is gone.
fn = (x -> 2*exp(x), x -> 2*sin(x))
@inline function test_calc(x, fn1, fn2)
@. x = x + fn1(x) + fn2(x)
end
function test()
A = Float64.(collect(1:10))
@time test_calc(A,x -> 2*exp(x), x -> 2*sin(x))
fn1, fn2 = fn
A = Float64.(collect(1:10))
@time test_calc(A, fn1, fn2)
A = Float64.(collect(1:10))
@time test_calc(A, fn...)
return nothing
end
Run test() twice time, you get:
julia> test()
0.000006 seconds
0.000003 seconds
0.000003 seconds
I haven’t observe that case in Julia 1.6 and 1.8. They both have 6 allocations (without @inline):
julia> test()
0.000036 seconds (6 allocations: 128 bytes)
0.000026 seconds (6 allocations: 128 bytes)
0.000040 seconds (6 allocations: 128 bytes)
Also, if your anonymous function is complicated, you can add @inline to them to force inlining the function. like @inline(x -> 2*exp(x)).