I’m working on a simulation in Julia, where the “centrepiece” is some struct, which can have a few boolean properties associated with it.
mutable struct Sim
""" data """
prop_a::Bool
prop_b::Bool
...
end
In the simulation I call a function to get the some energy dependent on this struct ten-thousands to millions of times, let’s call this function getE(s::Sim)
. Any of the properties being false, means that I don’t want to include some term in this energy function, and thus can speed up this function by not checking a few of the data fields in the struct (which would otherwise be accessing the fields to add zeros to some float in the end).
Thus, in other words the implementation of getE
depends on the properties of s
. I can some if statements and only access the fields the corresponding properties are true. This is quite fast, but there still is a small performance hit, especially if I need to do multiple checks.
I thought it might be faster to just write all the functions beforehand and save one of them in the Sim struct itself. Thus
mutable struct Sim
""" data """
prop_a::Bool
prop_b::Bool
...
efunc::Function
end
When I change one of the props, which doesn’t happen often, I just change the function being referenced in the struct, so that no checks have to be done at runtime. Sadly, the performance hit by accessing the referenced function turns out to be orders of magnitude higher than checking the properties every time.
julia> @btime getE(s)
13.556 ns (0 allocations: 0 bytes)
julia> @btime getECheckProp(s)
14.404 ns (0 allocations: 0 bytes)
julia> @btime s.efunc(s)
53.287 ns (1 allocation: 16 bytes)
Here getE(s)
is the base algorithm, getECheckProp(s)
checks the corresponding properties before calling getE(s)
, and s.efunc
is just a reference to getE
directly.
Any suggestions of how I could build my program to get as close to the performance of calling getE(s)
directly?