# Function compiles every time

**URL:** <https://discourse.julialang.org/t/function-compiles-every-time/63273>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 21, 2021, 5:04am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273 "2021-06-21T05:04:09Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![cadojo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cadojo/32/25328_2.png) [@cadojo](https://discourse.julialang.org/u/cadojo)\
**Post date:** [June 21, 2021, 5:04am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/1 "2021-06-21T05:04:10Z")

</div>

I re-wrote my astrodynamics functions with `ModelingToolkit`. Now, when I call `DifferentialEquations.solve(...)` in my wrapper function, it compiles every time. Is there any way to check _what_ is compiling?

```julia
using StaticArrays
using AstrodynamicalModels
using DifferentialEquations

function propagate(r, v, T; kwargs...)

  defaults = (; reltol=1e-14, abstol=1e-14, save_everystep=false)
  options = merge(defaults, kwargs)

  problem = ODEProblem(R2BP, MVector{6}(vcat(r,v)), (0.0, T), MVector{1}(398600.435))
  solutions = solve(problem; options...)

end

r = randn(3) * 1e4
v = randn(3) * 1e3
T = 10_000.0

@time propagate(r,v,T) # 28.067676 seconds (93.98 M allocations: 5.404 GiB, 3.61% gc time)
@time propagate(r,v,T) # 7.187065 seconds (13.05 M allocations: 704.718 MiB, 1.34% gc time, 99.70% compilation time)
@time propagate(r,v,T) # 7.154281 seconds (13.06 M allocations: 705.808 MiB, 1.79% gc time, 99.43% compilation time)

```

If I _don’t_ put the solver in a function, the behavior is fine.

```nohighlight
using StaticArrays
using AstrodynamicalModels
using DifferentialEquations

defaults = (; reltol=1e-14, abstol=1e-14, save_everystep=false)
kwargs = (;)
options = merge(defaults, kwargs)

r = randn(3) * 1e4
v = randn(3) * 1e3
T = 10_000.0

problem = ODEProblem(R2BP, MVector{6}(vcat(r,v)), (0.0, T), MVector{1}(398600.435))

@time solutions = solve(problem; options...) # 15.728376 seconds (50.96 M allocations: 2.763 GiB, 4.17% gc time, 2.34% compilation time)
@time solutions = solve(problem; options...) # 0.012221 seconds (540.66 k allocations: 9.171 MiB)
@time solutions = solve(problem; options...) # 0.012453 seconds (540.66 k allocations: 9.171 MiB)

```

**What am I doing wrong?**

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 21, 2021, 6:02am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/2 "2021-06-21T06:02:50Z")

</div>

Is `R2BP` an `ODESystem`? `ODESystem`s are symbolic objects, so every time you go symbolic → code it has to compile. I would recommend compiling it once and then using tools like `remake` to change `u0`, `tspan`, and `p`.

---

<div class="post-metadata">

**Author:** ![cadojo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cadojo/32/25328_2.png) [@cadojo](https://discourse.julialang.org/u/cadojo)\
**Post date:** [June 21, 2021, 4:34pm UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/3 "2021-06-21T16:34:12Z")

</div>

Ah I see. @ChrisRackauckas what constitutes “compiling” in this case? If I’m exporting an `ODESystem` that I don’t expect users to really change, should my package also export `ODEFunction` objects? Are `ODEFunction`s compiled?

I tried checking `Catalyst.jl` source code but couldn’t answer my question.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 21, 2021, 5:02pm UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/4 "2021-06-21T17:02:07Z")

</div>

> [@cadojo](#):
>
> Are `ODEFunction` s compiled?

Yes they are.

> [@cadojo](#):
>
> Ah I see. @ChrisRackauckas what constitutes “compiling” in this case?

It builds a new source for a function `f`, so it’ll need to compile again when it’s rebuilt. There may be a way to fix that though… @c42f is there a way to make runtimegeneratedfunctions cache this better? They should have the same hash.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [June 22, 2021, 6:56am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/5 "2021-06-22T06:56:21Z")

</div>

> [@ChrisRackauckas](#):
>
> There may be a way to fix that though… @c42f is there a way to make runtimegeneratedfunctions cache this better? They should have the same hash.

If the expressions have exactly the same hash this should already work.

Demo:

```julia
julia> using RuntimeGeneratedFunctions

julia> ex = :(x -> x^2 - 1)
:(x->begin
          #= REPL[2]:1 =#
          x ^ 2 - 1
      end)

julia> RuntimeGeneratedFunctions.init(Main)

julia> f = @RuntimeGeneratedFunction(ex)
RuntimeGeneratedFunction(#=in Main=#, #=using Main=#, :((x,)->begin
          #= REPL[2]:1 =#
          x ^ 2 - 1
      end))

julia> @time f(1.0)
  0.051278 seconds (64.49 k allocations: 4.051 MiB, 99.96% compilation time)
0.0

julia> @time f(1.0)
  0.000004 seconds (1 allocation: 16 bytes)
0.0

julia> g = @RuntimeGeneratedFunction(ex)
RuntimeGeneratedFunction(#=in Main=#, #=using Main=#, :((x,)->begin
          #= REPL[2]:1 =#
          x ^ 2 - 1
      end))

julia> @time g(1.0)
  0.000008 seconds (1 allocation: 16 bytes)
0.0

julia> typeof(f) === typeof(g)
true

```

Maybe the hashes aren’t exactly equal here for some reason?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 22, 2021, 9:25am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/6 "2021-06-22T09:25:44Z")

</div>

```julia
:(function (var"##out#1185", var"##arg#1183", var"##arg#1184", t)
      #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:282 =#
      #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:283 =#
      let var"x(t)" = #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:169 =# @inbounds(var"##arg#1183"[1]), τ = #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:169 =# @inbounds(var"##arg#1184"[1])
          #= C:\Users\accou\.julia\packages\Symbolics\sITWZ\src\build_function.jl:331 =#
          #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:329 =# @inbounds begin
                  #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:325 =#
                  var"##out#1185"[1] = (*)((inv)(τ), (+)(1, (*)(-1, var"x(t)")))
                  #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:327 =#
                  nothing
              end
      end
  end)
(generate_function(sys))[2] = :(function (var"##out#1188", var"##arg#1186", var"##arg#1187", t)
      #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:282 =#
      #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:283 =#
      let var"x(t)" = #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:169 =# @inbounds(var"##arg#1186"[1]), τ = #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:169 =# @inbounds(var"##arg#1187"[1])
          #= C:\Users\accou\.julia\packages\Symbolics\sITWZ\src\build_function.jl:331 =#
          #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:329 =# @inbounds begin
                  #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:325 =#
                  var"##out#1188"[1] = (*)((inv)(τ), (+)(1, (*)(-1, var"x(t)")))
                  #= C:\Users\accou\.julia\packages\SymbolicUtils\kZD5O\src\code.jl:327 =#
                  nothing
              end
      end
  end)

```

Every time it generates the function it increments the gensyms. There’s probably a way to fix that? It’s all fine locally since these functions can’t hit globals.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 22, 2021, 10:29am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/7 "2021-06-22T10:29:31Z")

</div>

@cadojo the better fix is [Unique function argument names for no recompilation by ChrisRackauckas · Pull Request #272 · JuliaSymbolics/Symbolics.jl · GitHub](https://github.com/JuliaSymbolics/Symbolics.jl/pull/272)

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [June 23, 2021, 6:58am UTC](https://discourse.julialang.org/t/function-compiles-every-time/63273/8 "2021-06-23T06:58:11Z")

</div>

Nice! Yes I wondered if it was upstream a little from `RuntimeGeneratedFunctions`.
