So it automatically promotes to the type “Function”. Next if I try evaluating this on a vector of random numbers
x = randn(100000)
@time for ii in eachindex(vsin)
0.012697 seconds (498.98 k allocations: 9.140 MiB)
@time for ii in eachindex(vf)
0.012592 seconds (498.98 k allocations: 9.140 MiB)
So performance is nearly identical in these cases. So is Function a special kind of abstract type that doesn’t suffer from performance in comparison to its concrete types, or is the performance penalty of abstraction hidden in the cost of something else (like calculating sin)? If I could break down common calculations into say, 20 categories, would it be worth the effort of grouping them into a NamedTuple of vectors (one vector for each calculation category) or would I be okay just lumping them into a single vector and getting their outputs (which are all Float64)?
julia> function test(v, x)
y = similar(x)
for ii in eachindex(v)
y[ii] = v[ii](x[ii])
julia> using BenchmarkTools
julia> @btime test($vsin, $x);
1.561 ms (2 allocations: 781.30 KiB)
julia> @btime test($vf, $x);
6.122 ms (299491 allocations: 5.33 MiB)
Interestingly, if it’s known to be a small union of functions, one may use
Right, thanks for the benchmarking tips! Unfortunately, the union of functions is unknown and would be pretty big in most cases. In one application they might be about 20-50 calculation types, in another application there might be more than a thousand.
That being said, the penalty only seems to be slowing it by a factor of 4 for a basic calculation. The calculations I plan on running are likely going to be more involved and include dictionary lookups, so the real-world impact of putting different functions together like this is probably going to be smaller with a huge benefit for simplification.
Oh neat! I didn’t know that! I do know all the input and output type signatures (the input is always a single dataframe and the output is always a vector of floats). I don’t see much documentation here. How would I actually use it to wrap a function?