I have some code that generates a lot of function calls within different code branches. Each function call generates a different function instance. All these function instances are getting precompiled when my module is precompiled, which is killing the precompilation time. The thing is, even though many functions are instantiated (i.e. a call exists in the code), very few of them will actually get called. I would like to ensure that certain functions are only compiled when they are actually called, and not when they are instantiated. Is this possible?
Here is a MWE of the problem:
function valuedispatch_expr(::Val{lower}, ::Val{upper}, val, fun) where {lower, upper}
if lower >= upper
return :( $fun(Val($upper)) )
end
midpoint = lower + div(upper - lower, 2)
expr_a = valuedispatch_expr(Val(lower), Val(midpoint), val, fun)
expr_b = valuedispatch_expr(Val(midpoint+1), Val(upper), val, fun)
return quote
if $val <= $midpoint
$expr_a
else
$expr_b
end
end
end
macro valuedispatch_macro(lower::Int, upper::Int, val, fun)
ex = valuedispatch_expr(Val(lower), Val(upper), esc(val), esc(fun))
quote
$ex
return nothing
end
end
@eval valuedispatch_1_32(val, fun) = @valuedispatch_macro(1, 32, val, fun)
@generated function myfun(::Val{v}) where v
println("Compiling ", v)
return :(println("Running ", $v))
end
println(valuedispatch_1_32(3, myfun))
While only one function actually gets called, 32 get compiled.
EDIT: At first I thought this might be because the compiler wants to understand the output type, so needs to compile all functions for that reason. However, I’ve now changed the code so that the valuedispatch
function always returns nothing
. The problem still persists.