I have a recursive function which operates a binary tree of integers, implemented as a nested pair of pairs or ints. My function creates a new tree with a different structure, and calls itself recursively until some condition is met. The issue I'm finding is that the first time the code is run, it takes a really long time to JIT compile all the possible signatures of the function; afterwards it runs fine.
Here is minimal working example:
my_tree = ((((6 => 7) => (6 => 7)) => ((7 => 7) => (0 => 7))) => (((8 => 7) => (7 => 7)) => ((8 => 8) => (8 => 0)))) => ((((2 => 4) => 7) => (6 => (0 => 5))) => (((6 => 8) => (2 => 8)) => ((2 => 1) => (4 => 5))))
function tree_reduce(tree::Pair)
left, right = tree
left isa Pair && (left = tree_reduce(left))
right isa Pair && (right = tree_reduce(right))
return left + right
end
@show my_tree
@show tree_reduce(my_tree)
using MethodAnalysis
methods = methodinstances(tree_reduce)
@show length(methods)
Although this example is not perceptually slow, it still generates 9 method instances for:
tree_reduce(::Pair{Pair{Pair{Int64, Int64}, Pair{Int64, Int64}}, Pair{Pair{Int64, Int64}, Pair{Int64, Int64}}})
tree_reduce(::Pair{Pair{Int64, Int64}, Pair{Int64, Int64}})
tree_reduce(::Pair{Int64, Int64})
tree_reduce(::Pair{Pair{Pair{Pair{Int64, Int64}, Int64}, Pair{Int64, Pair{Int64, Int64}}}, Pair{Pair{Pair{Int64, Int64}, Pair{Int64, Int64}}, Pair{Pair{Int64, Int64}, Pair{Int64, Int64}}}})
etc ...
Is there a way of avoiding this / precompiling / speeding it up / writing a generic function / running particular (part of) a function in an interpreted mode? I would be prepared to make the overall performance of the code slightly works at the pice of having it run faster on the first top-level call to tree_reduce.