# Unpredictable Compilation Performance of MTK-Generated Functions

**URL:** <https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827>\
**Category:** Modelling & Simulations\
**Tags:** modelingtoolkit, symbolics\
**Created:** [April 22, 2026, 11:37am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827 "2026-04-22T11:37:04Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 11:37am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/1 "2026-04-22T11:37:04Z")

</div>

**Problem Statement:** I am reporting a critical bottleneck regarding the compilation and loading stability of functions generated by `ModelingToolkit.jl`. My experience shows that the complexity of the generated symbolic Jacobian can lead to an “infinite” compilation hang, where performance is no longer correlated with the system’s dimensionality.

**Evidence of Performance Instability:** I compared two different system configurations, and the results demonstrate that MTK’s symbolic compilation path is highly unpredictable:

- **Case 1 (Sparse, ~2000 dims):** A high-dimensional system with a sparse structure. MTK handles this reasonably well; the `ODEProblem` construction and the first `solve` call (Jacobian compilation) finish within an acceptable timeframe.

- **Case 2 (Dense, ~200 dims):** A much smaller system but with a dense/highly-coupled structure. Despite having **10x fewer variables** , the compilation of `prob.f.jac` (triggered during the first `solve`) runs for over 30 minutes and fails to complete, consuming excessive memory.

- **The Argument:** This inconsistency suggests that the **symbolic expression swell** generated by MTK for coupled systems creates an AST so complex that it overwhelms the LLVM backend.

- **Compilation vs. Runtime:** While MTK aims for fast runtime, the “compilation wall” for dense systems makes the workflow unusable. The time saved during integration is irrelevant if the function takes 30+ minutes just to load.

- **Dimensionality is a Poor Metric:** Currently, users cannot predict whether a model will compile based on its size. A smaller, coupled model is significantly harder for MTK to “load” than a larger, sparse one.

**Conclusion:** The performance of the symbolic compilation path is currently a “black box.” We need a more robust way to handle or detect when symbolic expansion becomes a liability. Is there a plan to make the generated function overhead more predictable, or to provide a stable fallback when the symbolic Jacobian size exceeds a reasonable complexity threshold?

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [April 22, 2026, 12:28pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/2 "2026-04-22T12:28:24Z")

</div>

This looks like LLM generated output? It’s not allowed to post that directly: [Guidelines - Julia Programming Language](https://discourse.julialang.org/guidelines)

The model code is almost always the problem. So for someone to help, you need ideally an MWE or at least some code to understand what is going on.

Anyway, this has come up before. I think packages like GraphDynamics.jl were created to work around it. Maybe Chris can say more.

---

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [April 22, 2026, 12:29pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/3 "2026-04-22T12:29:46Z")

</div>

I know my comment is offtopic but I just found it ironic that the OP is posting an LLM generated output with a user name with the word “hardworking”.

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 2:35pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/4 "2026-04-22T14:35:46Z")

</div>

This is not genetated by LLM. But the translation is done with LLM. the complte code is to long, this is what i truely encounter. x\_syms = equilibrium\_state\_syms(model)  
p\_syms = full\_param\_syms(model)

```
residual = vcat(model.F_V, model.f_delta)

N_V = Symbolics.jacobian(model.F_V, model.V) # n × n
N_delta = Symbolics.jacobian(model.F_V, model.delta) # n × (n-1)
Cmat = Symbolics.jacobian(model.f_delta, model.V) # (n-1) × n

compiled_sys = mtkcompile(model.sys)

residual_fun = build_function(residual, x_syms, p_syms; expression = Val(false))[1]
M_fun = build_function(model.M, x_syms, p_syms; expression = Val(false))[1]
F_V_fun = build_function(model.F_V, x_syms, p_syms; expression = Val(false))[1]
f_delta_fun = build_function(model.f_delta, x_syms, p_syms; expression = Val(false))[1]

N_V_fun = build_function(N_V, x_syms, p_syms; expression = Val(false))[1]
N_delta_fun = build_function(N_delta, x_syms, p_syms; expression = Val(false))[1]
C_fun = build_function(Cmat, x_syms, p_syms; expression = Val(false))[1]

```

, for dense model, F\_V\_fun , f\_delta\_fun takes very very long time to load

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 2:41pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/5 "2026-04-22T14:41:47Z")

</div>

Now I tents to construct the system complete numerically. I have done a lot of comparisons, as shown below.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/c/2cafe0e220bb42810d4e5e12f97b3cf48080c93b.png)

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 2:52pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/6 "2026-04-22T14:52:12Z")

</div>

V0 = v\_ms;

δ0 = angs\_pv;

u0 = vcat(V0, δ0);

# consistent du0 from explicit RHS

du0 = make\_consistent\_du0(u0, p, obs, cache)

# residual function

dae\_residual! = make\_dae\_residual(obs, cache)

# check consistency

res0 = similar(u0)

dae\_residual!(res0, du0, u0, p, 0.0)

println("initial residual norm = ", norm(res0))

# all states are differential variables

differential\_vars = [true for \_ in 1:length(u0)]

# time span

tspan = (0.0, 2.0)

# DAE problem

prob = DAEProblem(

dae\_residual!,

du0,

u0,

tspan,

p;

differential\_vars = differential\_vars,

)

# Solve with Sundials IDA

sol = solve(

prob,

IDA(linear\_solver = :Dense),

reltol = 1e-8,

abstol = 1e-10,

saveat = 1e-3,

)

println("retcode = ", sol.retcode)

println("final state = ", sol.u[end])

## 

us = hcat(sol.u…);

fig = Figure()

ax = Axis(fig[1, 1])

[lines!(ax, sol.t, us[k, :]) for k in 1:n]

fig When the model is completed by numerically, the speed is very fast. When the node model dynamics are complete identical, the numerical model is easy to write, when the node model, branch model are diverse, generating model numerically take a lot of efferts, and are not modular. I do not put the codes, because the codes are too long, and I use MTK for almost a year, I think that is a really general problem, and i want to know whether some prominent improvments are possible. Currently I try to switch to numeric model, especially for a little big model.

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 2:54pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/7 "2026-04-22T14:54:46Z")

</div>

How can you see the problem that are generated by LLM???

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 22, 2026, 2:58pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/8 "2026-04-22T14:58:42Z")

</div>

I’ve been tormented by this question for the last week, your answers really annoy me.

data = load(“EMT-network/case300.jld2”)

bus = data[“bus”];

branch = data[“branch”];

gen = data[“gen”];

old\_to\_new = make\_continuous\_bus!(bus, branch, gen)

## power data

include(“E:/papers/ObGFM\_multi/powernet\_funcs.jl”)

include(“E:/papers/ObGFM\_multi/obgfm\_funcs.jl”)

include(“E:/papers/ObGFM\_multi/obgfm\_anal.jl”)

slack\_bus = findfirst(bus[:, 2] .== 3) # Slack节点

pv\_buses = findall(bus[:, 2] .== 2) # PV节点

pq\_buses = findall(bus[:, 2] .== 1) # PQ节点

Ybus = calc\_Ybus\_s(bus, branch)

θ0 = deg2rad.(bus[[slack\_bus; pv\_buses], 9]);

V0 = bus[[slack\_bus; pv\_buses], 8];

V\_re = V0 .\* exp.(1im .\* (θ0 .+ pi/2));

## initial conditions

Y\_red, Y\_s, elims = kron\_reduce(Ybus, [slack\_bus; pv\_buses]);

V\_eli = Y\_s\*V\_re;

idx = sortperm([elims; slack\_bus; pv\_buses])

V\_bus = [V\_eli; V\_re][idx];

angs = angle.(V\_bus) .- angle(V\_bus[slack\_bus]);

angs\_pv = angs[pv\_buses];

V\_ext = Y\_red_V\_re ._ (0.005+0.01\*1im) + V\_re

minimum(abs.(V\_ext))

maximum(abs.(V\_ext))

v\_ms = abs.(V\_ext)

prs = real.(V\_ext .\* conj.(Y\_red \* V\_re))

keys = Symbol.(“vg”, [slack\_bus; pv\_buses]);

gen\_types = [GFM\_observer\_re for \_ in [slack\_bus; pv\_buses]];

vgfs = Dict(keys .=\> gen\_types);

# paras = [(ko = 0.05, kv = 0.1, kp = 0.01, lg = 0.01, rg = 0.005),

# (ko = 0.01, kv = 0.1, kp = 0.01, lg = 0.01, rg = 0.005)];

para = (ko = 0.01, kv = 0.1, kp = 0.01, lg = 0.01, rg = 0.005);

paras = Dict(vg =\> para for vg in keys);

## === construct reduced Ybus matrix and parameters ===

extensions = [(idx, 1/(1im\*paras[vg].lg+paras[vg].rg)) for (idx, vg) in zip([slack\_bus; pv\_buses], keys)]

Y\_ext, node\_map = extend\_Ybus(Ybus, extensions)

node\_gfms = [node.new for node in node\_map]

Y\_gfms, \_ = kron\_reduce(Y\_ext, node\_gfms);

kos = [paras[vg].ko for vg in keys];

kvs = [paras[vg].kv for vg in keys];

kps = [paras[vg].kp for vg in keys];

## 

data = ObserverData(

ω\_b = 2π \* 60.0,

V0 = v\_ms,

δ0 = angs\_pv,

ko = kos,

kp = kps,

kv = kvs,

pr = prs,

vr = v\_ms,

G = real(Y\_gfms),

B = imag(Y\_gfms),

);

## 

n = length([slack\_bus; pv\_buses])

model = build\_reduced\_observer\_system(n);

ode\_sys = mtkcompile(model.sys)

u0 = state\_map(model, data)

p = param\_map(model, data)

prob = ODEProblem(ode\_sys, vcat(u0, p), (0.0, 2.0), jac = true)

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [April 22, 2026, 3:16pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/9 "2026-04-22T15:16:58Z")

</div>

This looks like powerflow, but I still don’t see any model code?

Can you format your code? You can edit your original comments. You can use triple backticks like this:

````julia-auto
/```
my code
```/

````

Without the /

See also: [Please read: make it easier to help you](https://discourse.julialang.org/t/please-read-make-it-easier-to-help-you/14757)

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [April 22, 2026, 6:18pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/10 "2026-04-22T18:18:18Z")

</div>

At the end of the day, it is a (longstanding) limitation of MTK/Symbolics that compilation for large numbers of symbolic expressions (even ODE RHS functions, not just Jacobians), becomes too slow to be useful as the problem size increases. There have been attempts to speed this up in the past (JuliaSimCompiler was one attempt I think), but I’m not sure where the current efforts are in addressing this issue. @ChrisRackauckas previously mentioned that one simple fix/hack might be to chunk a function into sub-functions, but I don’t know if this has ever been explored in practice.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [April 22, 2026, 7:14pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/11 "2026-04-22T19:14:07Z")

</div>

> [@isaacsas](#):
>
> At the end of the day, it is a (longstanding) limitation of MTK/Symbolics that compilation for large numbers of symbolic expressions (even ODE RHS functions, not just Jacobians), becomes too slow to be useful as the problem size increases.

Well, according to our experience, MTK 11 is about 50 times faster than MTK 10. So the problem described here must be a very specific test case. Without executable code difficult to investigate.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [April 22, 2026, 7:18pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/12 "2026-04-22T19:18:00Z")

</div>

But do you generate MTK models with tens of thousands of expressions? Because that’s the bottleneck being hit here. Which I don’t think MTK v11 addresses either.

---

<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:** [April 22, 2026, 9:39pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/13 "2026-04-22T21:39:51Z")

</div>

Lots of little things. But first a high level thing. JuliaSimCompiler we learned a lot of things, but ultimately had to start over. MTK v11 made the symbolic side type stable which was orthogonal to the JSC thing of building easier functions to compile. That has been revived in DyadCompiler which plugs better with the normal MTK stack so easier to maintain and can layer more tricks, but most to come in this. Just had a live meeting with the crew today in Copenhagen to kick off the new effort here so we will see how it goes.

> [@chen\_hardworking](#):
>
> My experience shows that the complexity of the generated symbolic Jacobian can lead to an “infinite” compilation hang, where performance is no longer correlated with the system’s dimensionality.

Getting Jacobians via symbolics is almost always the wrong idea. Autodiff is simply going to be faster.

> [@langestefan](#):
>
> Anyway, this has come up before. I think packages like [GraphDynamics.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/GraphDynamics) were created to work around it. Maybe Chris can say more.

If you know a very specific structure of your problem, then directly building an optimized representation for it is always going to be a good way to get something good. GraphDynamics for example specializes on only having ODEs, causal connections, and graph connections. It directly generates to for loops with that exact structure. If your problem doesn’t fit that structure you’re out of luck, but if it does it’s a great modeling environment.

ModelingToolkit lives in the most pessimistic space of possibly any DAE relations and attempts to generate code for that. Ultimately it is nice because it’s tricks work everywhere, but you also have the problem that working very generically can be more difficult to get specific cases to full optimality without getting extra information from the user about structure. The general method has wide reach and keeps growing in what it covers, but ultimately expert knowledge will beat it until we get that encoded into the system, and there’s lots of domains to get in there so there’s plenty of room for other modeling frameworks.

> [@isaacsas](#):
>
> @ChrisRackauckas previously mentioned that one simple fix/hack might be to chunk a function into sub-functions, but I don’t know if this has ever been explored in practice

Structure recovery seems better to get to first because most people seem to have at least some structure, plus specializing out linear parts.

---

<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:** [April 22, 2026, 9:40pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/14 "2026-04-22T21:40:58Z")

</div>

Though I’ll say the Ordinarydiffeq v7 is taking a ton of attention right now, but hopefully is done this week…

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 23, 2026, 6:19am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/15 "2026-04-23T06:19:08Z")

</div>

[obgfm\_anal.jl](https://discourse.julialang.org/uploads/short-url/3q8dop0g5rdvF0doUzxq6NIfvf1.jl) (7.4 KB)  
[powernet\_funcs.jl](https://discourse.julialang.org/uploads/short-url/u7AsVDlawQ1ucrS6dUXhr5Q32eL.jl) (2.9 KB)  
[simulate - SM - 1.jl](https://discourse.julialang.org/uploads/short-url/o5sExrZuinDoZEH8061GaFKNGZD.jl) (3.7 KB)

I have uploaded a script for a small, dense model (Reduced model that negecting fast dynamics), and the `data.jld2` file is not allowed to upload. The code demonstrates a significant performance bottleneck: while symbolic generation for systems like IEEE-118 or IEEE-300 is acceptable, the overhead of creating an `ODEProblem` and executing the first `solve` is excessively high. Specifically, I require the Jacobian function for my analysis, but the initial call to `prob.f.jac` is extremely time-consuming. I initially suspected system scale was the issue, but even for small models.

The main function is `simulate-SM-1`. Currently, at this stage, I have to switch my model numerically.

---

<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:** [April 23, 2026, 8:24am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/16 "2026-04-23T08:24:52Z")

</div>

Can you put this to the issues in the repo? We use he issue list to sort and prioritize work, so it’ll get lost here but it’ll get discussion there.

> [@chen\_hardworking](#):
>
> Specifically, I require the Jacobian function for my analysis, but the initial call to `prob.f.jac` is extremely time-consuming. I initially suspected system scale was the issue, but even for small models.

ForwardDiff.jacobian is likely a better way to handle this.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [April 23, 2026, 10:19am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/17 "2026-04-23T10:19:50Z")

</div>

Would adding method splitting for the ODE rhs be that complicated to add? This is an issue that has come up for years, so perhaps getting some solution in, even if it is not ideal, would still be helpful? At this point I don’t know the Symbolics `build_function` code well enough to understand if it would be hard to see that the list of symbolic expressions / equations is over some threshold and then start splitting them up (or to at least add this as a kwarg that can be turned on). But at a high level this doesn’t sound like it would be that big a modification to implement in a crude way?

---

<div class="post-metadata">

**Author:** ![GeorgeGkountouras](https://avatars.discourse-cdn.com/v4/letter/g/77aa72/32.png) [@GeorgeGkountouras](https://discourse.julialang.org/u/GeorgeGkountouras)\
**Post date:** [April 23, 2026, 9:41pm UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/18 "2026-04-23T21:41:30Z")

</div>

> [@chen\_hardworking](#):
>
> - **Compilation vs. Runtime:** While MTK aims for fast runtime, the “compilation wall” for dense systems makes the workflow unusable. The time saved during integration is irrelevant if the function takes 30+ minutes just to load.

While I agree with the general sentiment, in the audio domain I would be happy with an “offline” compilation step that takes 3 days if it makes the “realtime” solve faster.

---

<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:** [April 24, 2026, 5:13am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/19 "2026-04-24T05:13:29Z")

</div>

> [@GeorgeGkountouras](#):
>
> While I agree with the general sentiment, in the audio domain I would be happy with an “offline” compilation step that takes 3 days if it makes the “realtime” solve faster.

To deal with these competing demands, MTK is going to need to adopt the specialization levels that SciMLBase introduced for the latency handling, i.e. NoSpecialize vs AutoSpecialize vs FullSpecialize. In AutoSpecialize, we definitely can compile less by actually just (symbolically) interpreting a lot of expressions, that will never hit the Julia compiler but will just be runtime slower. In many cases it’s likely fast enough to not even show up in any profile in any meaningful way. One place where this is likely true is `remake` if you choose a subset of variables, where we have to build the symbolic change functions and compile them, but in most cases it’s likely okay or even faster to just symbolically interpret that change via using `substitute`. But yes, then real-time audio applications will ask for the version that compiles absolutely everything to generate a really slim artifact. So I think we just need to end up with different levels where the user makes a choice for what balance is appropriate for their application, just like we did with the ODE. And with the ODE case, AutoSpecialization ended up being good enough that 99.9% of people probably don’t even touch that part and ways just do the auto form, so it ends up just being a latency improvement without a meaningful runtime hit.

> [@isaacsas](#):
>
> At this point I don’t know the Symbolics `build_function` code well enough to understand if it would be hard to see that the list of symbolic expressions / equations is over some threshold and then start splitting them up (or to at least add this as a kwarg that can be turned on). But at a high level this doesn’t sound like it would be that big a modification to implement in a crude way?

The difficult part is that the separating needs to be done not too crudely as it can get expensive itself. The easiest way to get the linear part is to take the Jacobian and grab all the constants, and then diff them out of the equation by running simplify. That simplify can be a lot of simplifies though, so that can be slow. Dhariya does have a good working code for this though that improves PDE cases like Bruss and I’m having him look at BCR next. This is getting the whole compiler team involved as it’s actually turned into quite a difficult (/interesting) problem.

---

<div class="post-metadata">

**Author:** ![chen\_hardworking](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chen_hardworking/32/219649_2.png) [@chen\_hardworking](https://discourse.julialang.org/u/chen_hardworking)\
**Post date:** [April 24, 2026, 5:14am UTC](https://discourse.julialang.org/t/unpredictable-compilation-performance-of-mtk-generated-functions/136827/20 "2026-04-24T05:14:18Z")

</div>

MTK works exceptionally well for small-scale simulations and learning fundamental concepts, as it allows me to build models from first principles. I have also benefited a great deal from using it. My comment only reflects the practical challenges that arise specifically when compiling large-scale and complex models.
