# Understanding jump model preparation cost

**URL:** https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472
**Category:** Modelling & Simulations
**Tags:** question, sciml, modelingtoolkit
**Created:** [July 25, 2026, 6:24pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472 "2026-07-25T18:24:16Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [July 25, 2026, 6:24pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/1 "2026-07-25T18:24:16Z")

</div>

I am using Catalyst.jl to make `JumpProblem`s of around 160k species and a fairly sparse interaction structure that includes what JumpProcesses.jl calls “constant-rate jump” (CRJ) reactions. This works, but `JumpProblem` construction is quite slow (and so is integrator initialization). I would like to understand why that is and what I could do about it.

As an (admittedly contrived) example, consider:

```julia-auto
using Catalyst
using Graphs
using JumpProcesses

t0 = @elapsed begin
	g = static_scale_free(n, 2n, 3.0, 3.0, seed = n)
	t = default_t()
	xs = map(vertices(g)) do i
		name = Symbol("node_$i")
		only(@species $name(t))
	end
	rate(i) = minimum(
		[hill(xs[j], 1.0, 1 / j, 1.0) for j in neighbors(g, i)],
		init = 1.0,
	)
	reactions = mapreduce(vcat, vertices(g)) do i
		[
			Reaction(rate(i), nothing, [xs[i]])
			Reaction(1.0, [xs[i]], nothing)
		]
	end
	system = complete(ReactionSystem(reactions, name = :name))
end
t1 = @timed JumpProblem(system, [s => 0 for s in unknowns(system)], (0.0, 1.0))

```

This builds a directed graph with n nodes, 2n edges and a power-law degree distribution, and then translates it into a reaction network such that the inbound edges are aggregated for each species (node) by a CRJ function (here map `hill` and reduce by `minimum`). Timing this construction for various sizes (on a smaller 2019 Intel laptop, no swap) gives:

 ![total-times](https://global.discourse-cdn.com/julialang/original/3X/7/3/7385ca67e50c6b74981c68324739cdc3c6aeb15e.png)  
(I have attached a [Pluto notebook](https://discourse.julialang.org/uploads/short-url/qYpYrB3nidzs1UAUJV2Qv20Sb23.jl) (113.9 KB) timing the `JumpProblem` call, but not the integrator initialization. Apparently I am not allowed to upload the CSV file with the timings?)

Although this isn’t really a clean benchmark, it still shows what I observed in my actual application: Constructing the model specification is negligibly fast, but the `JumpProblem` call is very expensive. Without having a good mental model of what exactly it does internally, my expectation would be that it should take time and memory proportionally to the number of links (i.e. here, O(n)). But beyond a certain size, both time spent and memory allocated grow faster than the link count:

 ![cost-per-link](https://global.discourse-cdn.com/julialang/original/3X/0/4/0472710c97fb6a3fab1b20bcb5700a02d5456ea4.png)

Whenever I send `SIGUSR1`, it is currently doing `assemble_crj`/`compile_equational_affect` (for `JumpProblem` construction) or `concretize_affects!` (for integrator initialization). Since the timings show that most of that is Julia compiling stuff, I suspect that model preparation actually compiles these many ~~rate~~ update functions one-by-one. _(Edit: “affect” actually refers to the state updates, right?)_

In my application (which is ~160k species, ~64k CRJ-rate reactions, and ~300k purely mass-action reactions, run on a passively cooled Ryzen 9 HX 370, so effectively laptop hardware) `JumpProblem` construction takes ~36h, and the first integrator intitialization ~14½h. But each subsequent integrator initialization, despite being produced from a `deepcopy`d `JumpProblem` (!), is fast enough that I am unsure whether the delay might actually just have been faster reaction propensities early on. And the whole process takes ~18GiB peak resident memory, most of which seems to be for SciML, let’s call it 16GiB.

Now my questions are:

- Am I using this incorrectly? It feels like I’m missing something here. (Why does creating an integrator mutate the `JumpProblem`? Why is `JumpProblem` mutable in the first place, isn’t the whole point of having an integrator object to encapsulate the iteration and execution context?)
- Can I reduce the memory footprint somehow? ~100KiB per species (resp. ~50KiB per specified graph edge) seems quite high since I’m not saving trajectories.
- Why is preparation so slow in absolute terms? Are these ~~rate~~ update functions all individually optimized or something like that? _(Edit: “affect” = updates)_
- Why is preparation time super-linear in the number of species + links (which determine the complexity and size of the ~~rate~~ update functions)? _(Edit: I guess the same consideration holds for the updates, i.e. the complexity/size of the state updater would depend on the number of outbound edges?)_
- Given that subsequent initializations are faster despite the preceding `JumpProblem` `deepcopy`: What part of the execution state here is global? Do the rate functions all enter Julia’s method table?
- If so, will they be evicted at some point, or do I need to avoid processing a sequence of large SciML models in the same Julia process?
- Are there easy ways to accelerate model preparation? ~~E.g. by predefining/registering the rate functions somewhere, perhaps once for each arity, since they are so similar?~~ _(Edit: That probably does not make sense for the affects…)_ Otherwise, could their compilation be multi-threaded? (At that point I guess they would be independent of each other, right?)

---

<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: [July 27, 2026, 5:11pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/2 "2026-07-27T17:11:20Z")

</div>

Each Hill function reaction generates a new ConstantRateJump, which in turn requires two Julia functions to be built from the symbolic expressions (in the JumpProblem call) and compiled (I’m not sure where this happens currently, for ODEs I think it used to happen the first time the function was called). The translation from Catalyst to ModelingToolkit can be split from the function building if you use `jump_model` to do the conversion. This should be fast. Calling `JumpProblem` on that is where MTK then builds the Julia `ConstantRateJump` functions from the symbolic `ConstantRateJump`s, which is going to be slow with so many jumps. I don’t think these functions actually compile though, I’d have thought compilation occurs when they are first called in a Gillespie method (or maybe they compile when they are wrapped with FunctionWrappers during JumpProcess initialization).

I know the Julia compiler has issues with very large generated functions and a non-linear compilation time scaling there. It seems you are running into a similar issue with generating and compiling many many small functions. Unfortunately I think this is a fundamental ModelingToolkit limitation, but perhaps @ChrisRackauckas can say more.

We have discussed adding a custom `HillJump` type to JumpProcesses, which would serve as a aggregator for a collection of multiple Hill rates and potentially solve this issue for you, but I don’t think this is something I can promise in the next few months unfortunately.

---

<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: [July 27, 2026, 5:17pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/3 "2026-07-27T17:17:27Z")

</div>

`JumpProblem`s store the underlying aggregator that samples the next reaction and its time, and hence have internal state (i.e. the current jump intensities for example). This is a consequence of the design of JumpProcesses to use callbacks over the aggregation for providing next event times (so one can easily mix jumps with ODEs/SDEs). It is messy, but can’t really be changed without having a way to have a cache of the aggregator’s needed data that persists between simulations and is instead accessible via the integrator (which is not possible now as far as I am aware). Hence it has always been cached in the JumpProblem, the only other globally accessible simulation component.

---

<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: [July 27, 2026, 5:18pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/4 "2026-07-27T17:18:51Z")

</div>

The memory use you are seeing likely all just comes from compilation. If you are setting `save_positions = (false,false)` then the only memory being used should be the current state saving and the caching of current propensities (depending on the method you are using).

---

<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: [July 28, 2026, 8:42am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/5 "2026-07-28T08:42:05Z")

</div>

It’s not fundamental just hard. We are doing some weird stuff like:

> **[GitHub - SciML/RespecializeParams.jl: Type-stable opaque parameter containers for SciML...](https://github.com/SciML/RespecializeParams.jl)**
>
> Type-stable opaque parameter containers for SciML solvers: keep typeof(p) uniform across underlying payload types, recover the concrete type inside f without allocation.

mixed with FunctionWrappersWrappers.jl in order to despecialize callback generations while not losing performance. We’re continuing to improve the compile time performance but actually just in a meeting today we noted that large numbers of callbacks is still one area where we trip up, and that’s the jump process one. So all sorts of, function splitting, callback despecialization, function reuse caching, etc. is going on.

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [July 28, 2026, 9:40am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/6 "2026-07-28T09:40:08Z")

</div>

Thank you both for the info, am I then understanding correctly that:

- I am not using this incorrectly, and there is no easy way for me to improve this type of application right now?
- All of these many compiled entities will outlive the `JumpProblem` instance, so if I need to run multiple large models I need to do so in separate Julia processes?
- Tightly coupling these compiled entities with simulation state is an architectural decision in some underlying SciML package that cannot easily be changed? But this is mostly unrelated to my performance issue?

(Regarding the last point, I have found [this JumpProcesses.jl issue](https://github.com/SciML/JumpProcesses.jl/issues/554) that provides some context, but I still don’t understand why the “next reaction” identities and times have to be stored alongside the compiled stuff that might be expensive to recompute on a subsequent solve call but would not change across models /`JumpProblem`s. I guess I am asking why “callbacks” are more than a reference to executable code, also in non-jump problems. Isn’t that state only ever needed in the context of an integrator invocation? An independent solve call would need to reinitialize them anyway, no?)

> [@isaacsas](#):
>
> I don’t think these functions actually compile though, I’d have thought compilation occurs when they are first called in a Gillespie method (or maybe they compile when they are wrapped with FunctionWrappers during JumpProcess initialization).

It seems like some part (around ⅔) of the compilation happens in `JumpProblem` construction, and the rest during the first integrator invocation, so maybe when they are first called. But either way, (assuming that persistent memory usage is primarily due to the compiled CRJ callbacks) how are they so large, at dozens of kilobytes each? Wouldn’t “despecialization, function reuse caching etc.” _reduce_ their final size?

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [July 28, 2026, 9:51am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/7 "2026-07-28T09:51:04Z")

</div>

I am not sure if this is related, but after my most recent upgrade, `JumpProblem` memory usage has increased by at least an order of magnitude, and the process is now oom-killed after ~2min (at ~40GiB where previously at that time point it was at ~4GiB). I don’t yet know which package/version caused it, but had to downgrade from [new-Manifest.toml](https://discourse.julialang.org/uploads/short-url/rQCULVLzp06zVkevyQ7VIkpgAlh.toml) (82.6 KB, as of 2026-07-27) to [old-Manifest.toml](https://discourse.julialang.org/uploads/short-url/zpKapfxG7HVd2e6snRlamNpb6iy.toml) (82.9 KB, as of 2026-05-26) for now.

---

<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: [July 29, 2026, 1:48am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/8 "2026-07-29T01:48:39Z")

</div>

@cryptic.ax check for a regression?

---

<div class="post-metadata">

### Author: ![cryptic.ax](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cryptic.ax/32/220540_2.png) [@cryptic.ax](https://discourse.julialang.org/u/cryptic.ax)
#### Post date: [July 29, 2026, 6:52am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/9 "2026-07-29T06:52:54Z")

</div>

What value of `n` were you using for the model in the root of this thread? Or some other model entirely? We had a performance regression in a recent release, but I triggered registration for a new version with a fix a little while back.

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [July 29, 2026, 8:19am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/10 "2026-07-29T08:19:46Z")

</div>

For that example I am running `for n in 2 .^ (2:15)` to produce the figures as per the attached Pluto notebook.

So the used versions are:

| Package | old-Manifest.toml | Pluto notebook | new-Manifest.toml |
| --- | --- | --- | --- |
| ModelingToolkitBase | 1.40.0 | 1.54.1 | 1.57.0 |
| JumpProcesses | 9.29.0 | 9.29.2 | 9.29.2 |
| Catalyst | 16.1.1 | 16.2.2 | 16.2.3 |

Which version (of ModelingToolkitBase I presume) has the fix? (I am unsure now if the regression was already present in the Pluto notebook because there I don’t go as big as my actual model.)

Thanks for looking into it.

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [July 30, 2026, 5:55pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/11 "2026-07-30T17:55:02Z")

</div>

> [@cryptic.ax](#):
>
> We had a performance regression in a recent release, but I triggered registration for a new version with a fix a little while back.

The most current versions I get after running `]up` right now are:

- ModelingToolkitBase: v1.58.1
- SciMLBase: v3.39.1 (blocked from upgrading by DiffEqBase)
- DiffEqBase v7.9.0 (blocked from upgrading, unsatisfiable requirements for ImplicitDiscreteSolve, restricted by compatibility requirements with OrdinaryDiffEqCore: “no versions left”)

The excessive memory usage is still present, what version(s) do I need?

---

<div class="post-metadata">

### Author: ![cryptic.ax](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cryptic.ax/32/220540_2.png) [@cryptic.ax](https://discourse.julialang.org/u/cryptic.ax)
#### Post date: [July 31, 2026, 5:59am UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/12 "2026-07-31T05:59:22Z")

</div>

Those versions should be good. Can you share what you’re running to get this excessive memory usage?

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [August 1, 2026, 1:06pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/13 "2026-08-01T13:06:18Z")

</div>

Apologies for the delay, I had some trouble reducing this to a small reproducing example. The issue seems to be mixing integer states with float parameters. Maybe I’m also using this incorrectly, but as I said this previously ran fine (albeit very slowly like described above).

Run [timeit.jl](https://discourse.julialang.org/uploads/short-url/pfawTlXYiyiCZGHqq9wFPttBgwG.jl) (980 Bytes) in environment [Project.toml](https://discourse.julialang.org/uploads/short-url/dphEfQ5oKBhz5znFUdGWiytNgMF.toml) (12.3 KB), [Manifest.toml](https://discourse.julialang.org/uploads/short-url/j1j2tb7WFT3tDexolb9hHBLqL7W.toml) (82.0 KB), Julia v1.12.6: as soon as it starts building the JumpProblem it keeps grabbing more memory until it runs out (on my machine).

_Edit:_ I also find it surprising that the number of parameters reported changes from run to run, but it is always lower than what I would expect: 32768.

---

<div class="post-metadata">

### Author: ![estrella\_snyder35](https://avatars.discourse-cdn.com/v4/letter/e/db5fbb/32.png) [@estrella\_snyder35](https://discourse.julialang.org/u/estrella_snyder35)
#### Post date: [August 2, 2026, 8:45pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/14 "2026-08-02T20:45:39Z")

</div>

Have you tried timing the JumpProblem call with much simpler rate functions (like constants or linear expressions) to see if that compilation hypothesis holds up? If the slowdown is really baked into compiling individual CRJ affects, even a small test case with a few thousand species and complex rates should show the pattern. That might also tell you whether it’s the number of functions that matters or their complexity or what.

---

<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: [August 11, 2026, 6:29pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/15 "2026-08-11T18:29:39Z")

</div>

Sorry for the delayed reply; I was on vacation and am just now back at work.

> > I am not using this incorrectly, and there is no easy way for me to improve this type of application right now?

Not via Catalyst right now, no. This requires changes across SciML. If we wanted to avoid the memory / compilation issues that arise from having many many `ConstantRateJump` functions we would need to extend JumpProcesses to have a `HillFunctionJump` type or such, that works similar to `MassActionJump` in aggregating all such jumps into one entity. That is something that is doable in theory, but would require some work to integrate throughout the package and then propagate back up into ModelingToolkit and Catalyst. That said, @ChrisRackauckas has pointed out he has places this would be useful too, so it is probably something we should look into in the near future.

> > All of these many compiled entities will outlive the `JumpProblem` instance, so if I need to run multiple large models I need to do so in separate Julia processes?

No, they shouldn’t outlive a given problem instance. They will outlive a given solution instance since they are cached in the problem.

> > (Regarding the last point, I have found [this JumpProcesses.jl issue](https://github.com/SciML/JumpProcesses.jl/issues/554) that provides some context, but I still don’t understand why the “next reaction” identities and times have to be stored alongside the compiled stuff that might be expensive to recompute on a subsequent solve call but would not change across models /`JumpProblem`s. I guess I am asking why “callbacks” are more than a reference to executable code, also in non-jump problems. Isn’t that state only ever needed in the context of an integrator invocation? An independent solve call would need to reinitialize them anyway, no?)

> > Tightly coupling these compiled entities with simulation state is an architectural decision in some underlying SciML package that cannot easily be changed? But this is mostly unrelated to my performance issue?

What you don’t want to do is reallocate all the aggregator’s (i.e. Gillespie method’s) cache data structures each time you call `solve`. That can be more expensive than the simulation itself, and will lead to massive memory allocations when running many independent samples. Hence such structures / arrays are only allocated once during `JumpProblem` construction, and then reused each time `solve` is called (i.e. reinitialized but not reallocated). But none of this should have anything to do with the issues you are encountering as far as I am aware (which are more related to having many many many functions that are generated via MTK and then need to be complied).

> It seems like some part (around ⅔) of the compilation happens in `JumpProblem` construction, and the rest during the first integrator invocation, so maybe when they are first called. But either way, (assuming that persistent memory usage is primarily due to the compiled CRJ callbacks) how are they so large, at dozens of kilobytes each? Wouldn’t “despecialization, function reuse caching etc.” _reduce_ their final size?

This I can’t answer, but it seems like maybe there is a MTK issue here with the generated code. These should be very small functions that we subsequently wrap with a `FunctionWrapper`.

> Have you tried timing the JumpProblem call with much simpler rate functions (like constants or linear expressions) to see if that compilation hypothesis holds up? If the slowdown is really baked into compiling individual CRJ affects, even a small test case with a few thousand species and complex rates should show the pattern. That might also tell you whether it’s the number of functions that matters or their complexity or what.

This won’t work if your simpler examples are mass action, since they will generate a `MassActionJump` that handles all such reactions collectively. So one needs to have a custom rate law, or something beyond mass action to ensure one gets a `ConstantRateJump`. But a simple test would be just to hand code a `ConstantRateJump` for a Hill function and generate one via Catalyst, and then compare the function sizes after compilation (to be honest I’m not sure how to do this, but at one point one could get MTK to also return the generated function’s code to look over what it created, so perhaps that could help here).

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [August 16, 2026, 5:23pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/16 "2026-08-16T17:23:13Z")

</div>

Thank you for the detailed response.

> [@isaacsas](#):
>
> > > All of these many compiled entities will outlive the `JumpProblem` instance, so if I need to run multiple large models I need to do so in separate Julia processes?
> 
> No, they shouldn’t outlive a given problem instance. They will outlive a given solution instance since they are cached in the problem.

But why would creating the first integrator then be expensive, while creating subsequent integrators is quite fast, given I produce all of them from `deepcopy`d JumpProblems? Where is the necessary (presumably compiled) information retained if not in global state (such as Julia’s method table)?

> [@isaacsas](#):
>
> What you don’t want to do is reallocate all the aggregator’s (i.e. Gillespie method’s) cache data structures each time you call `solve`. That can be more expensive than the simulation itself

Isn’t this situation similar to asking users to `remake!` Problems instead of creating them anew? If there are many `solve` calls, cannot users also retain and reinitialize their integrators in the same way? (At least this is what we are doing.)

If this is too inconvenient, it sounds like there should be a shared integrator pool that “naked” `solve` calls will acquire from if possible and release to when finished. Maybe that pool should even be associated with the Problem object, it would never contain more integrators than threads. But the Problem could then still be treated as effectively immutable from the outside, and no deepcopying would be necessary. (I mean: include precompilation and other preparations directly in the Problem, immutably, and move everything that changes and the necessary caches into the integrators, since they must be independent between threads anyway.)

> [@estrella\_snyder35](#):
>
> If the slowdown is really baked into compiling individual CRJ affects, even a small test case with a few thousand species and complex rates should show the pattern. That might also tell you whether it’s the number of functions that matters or their complexity or what.

Didn’t I do just that in my OP?

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [August 16, 2026, 5:26pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/17 "2026-08-16T17:26:36Z")

</div>

> [@cryptic.ax](#):
>
> Those versions should be good. Can you share what you’re running to get this excessive memory usage?

Did you need additional input from me, and should I perhaps open an issue? If so, in which repo?

---

<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: [August 17, 2026, 10:02pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/18 "2026-08-17T22:02:35Z")

</div>

> [@lmshk](#):
>
> But why would creating the first integrator then be expensive, while creating subsequent integrators is quite fast, given I produce all of them from `deepcopy`d JumpProblems? Where is the necessary (presumably compiled) information retained if not in global state (such as Julia’s method table)?

I assume the first time you create an integrator compilation of the `ConstantRateJump`s is occurring, but not on subsequent integrators being created. But I’m honestly not sure what is going on at the Julia level.

There is a mechanism to reinitialize integrators, but it is not supported/used with EnsembleProblems and requires using the lower-level integrator interface. So that would need to be changed/generalized before we made such a change in JumpProcesses.

This [PR](https://github.com/SciML/JumpProcesses.jl/pull/570) was supposed to get rid of related issues for MassActionJumps and clean up the rng interface as part of the next breaking release. It got stalled waiting on stuff to get merged in lower-level packages until I didn’t have time to work on this more, but I’m hoping to resurrect it next month. I could look into adding integrator `reinit!` at that time, but I wouldn’t feel comfortable moving the cache structures out of the problem until we have an `EnsembleProblem` / ensemble solve generalization we could point people to as a new workflow.

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [August 18, 2026, 3:57pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/19 "2026-08-18T15:57:19Z")

</div>

> [@isaacsas](#):
>
> I assume the first time you create an integrator compilation of the `ConstantRateJump`s is occurring, but not on subsequent integrators being created.

At least part of it (as most of it seems to be done directly on `JumpProblem` construction). If that is the case, they will never go away, right? And if I want to reclaim the memory I’d need to run larger models in their own Julia process in the first place?

> [@isaacsas](#):
>
> There is a mechanism to reinitialize integrators, but it is not supported/used with EnsembleProblems and requires using the lower-level integrator interface.

To your knowledge, would this require more than just clearing out the saved trajectories and then doing something like the following?

```julia
integrator.t = ...
for s in SymbolicIndexingInterface.variable_symbols(integrator)
    integrator[s] = ...
end
JumpProcesses.reset_aggregated_jumps!(integrator)

```

(I’m asking also because we are doing something like that to transfer the initial state into the integrator and I want to make sure I didn’t miss anything.)

* * *

Anyway, I think my original questions have been answered (thank you @isaacsas) unless someone has more background info about that compilation issue, in particular where all of that memory is used and why this is super-linear in problem size? It sounds to me like currently there is nothing simple I can do about these points. But I’d really like to know if there’s somewhere I can track work on that memory regression?

---

<div class="post-metadata">

### Author: ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)
#### Post date: [September 23, 2026, 1:32pm UTC](https://discourse.julialang.org/t/understanding-jump-model-preparation-cost/138472/20 "2026-09-23T13:32:43Z")

</div>

We have identified the SymbolicUtils.jl commit that introduced the issue. I have opened [an issue](https://github.com/JuliaSymbolics/SymbolicUtils.jl/issues/1098). Here are the Manifests for the reproducing example given there: [Manifest.good.toml](https://discourse.julialang.org/uploads/short-url/nJkx8Eaq63tDVZavsFVxJgQdUh8.toml) (70.9 KB), [Manifest.bad.toml](https://discourse.julialang.org/uploads/short-url/jLYU7JvHoSIkS0UaVmVSdD22ZLG.toml) (70.9 KB).
