I checked with a profiler and got
using BenchmarkTools
abstract type equation_nodes end
struct opera_node{L, R} <: equation_nodes
arity::Int64; opera::Int64
lef::L; rig::R
opera_node(a::Int64, o::Int64) = new{Nothing, Nothing}(a, o, nothing, nothing)
opera_node(a::Int64, o::Int64, l::L) where {L} = new{L, Nothing}(a, o, l, nothing)
opera_node(a::Int64, o::Int64, l::L, r::R) where {L, R} = new{L, R}(a, o, l, r)
end
struct const_leav <: equation_nodes
value::Float64
end
struct varia_leav <: equation_nodes
value::Int64
end
function eval_equation(eq, vars, ops)
if typeof(eq) <: const_leav
zeros = vars[1] .- vars[1] # to get a 0.0-tuple of appropriate length
cur_val = zeros .+ eq.value # and ensure to return always same type
elseif typeof(eq) <: varia_leav
cur_val = vars[eq.value]
elseif eq.arity == 1
lef = eval_equation(eq.lef, vars, ops)
cur_val = ops[eq.opera].(lef)
elseif eq.arity == 2
lef = eval_equation(eq.lef, vars, ops)
rig = eval_equation(eq.rig, vars, ops)
cur_val = ops[eq.opera].(lef, rig)
else
cur_val = nothing
end
return cur_val
end
@btime eval_equation(eq1, vars, ops) setup = (
eq1 = opera_node(2, 1, varia_leav(1), varia_leav(2));
vars = ((1.0, 2.0, 3.4, 4.1, 5.3, 6.3), (7.0, 2.0, 2.4, 1.1, 5.0, 6.4));
ops = (+, -, *, /, cos)
)
yielding
1.200 ns (0 allocations: 0 bytes)
Edit: eliminated the last allocation via benchmark setup, now constant propagation does it’s job ![]()