# \[BoundaryValueDiffEq.jl\] Reducing allocations

**URL:** <https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255>\
**Category:** New to Julia\
**Tags:** differentialequation\
**Created:** [March 18, 2026, 2:05pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255 "2026-03-18T14:05:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![MaxSchelski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxschelski/32/221245_2.png) [@MaxSchelski](https://discourse.julialang.org/u/MaxSchelski)\
**Post date:** [March 18, 2026, 2:05pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/1 "2026-03-18T14:05:20Z")

</div>

Hi,

I started to implement my Python pipeline for solving boundary value problems in Julia using BoundaryValueDiffEq.jl. I tried to optimize the functions but I am wondering if it is possible to increase performance further by reducing the number of allocations. In the minimal reproducible example below I can’t get below 440 k allocations. Is there any additional optimization I could try or are the numbers of allocations I am getting as good as it gets?

```julia-auto
import BoundaryValueDiffEq as BVP

function distribution_fun_test!(dydt::AbstractVector{T}, y::AbstractVector{T}, p::Any, #
                                t::Float64) where {T<:Real}

    y1, y2, y3, y4 = y

    dydt[1] = 0.001 * y2
    dydt[2] = 10 * y1
    dydt[3] = -0.03 * y2 + 0.0001 * y4
    dydt[4] = 10 * y3
                    
    uptake = 0.1 * y3 / (1000 * y3 + 1)
    dydt[3] += uptake
end

function distribution_bc_test!(residual::AbstractVector{}, u::Any, p::Any, t::Vector{Float64})

    residual[1] = (u[4, end] - 0.001)
    residual[2] = u[1, end]
    residual[3] = (- u[3, end])
    residual[4] = (u[1, 1])

end

function test_solve()
    L = 100.0
    mesh_size = 500
    tspan::Tuple{Float64, Float64} = (0.0, Float64(L))

    y_initial::Vector{Float64} = [1, 0.001/0.03, 1, 0.001]

    bvp_problem = BVP.BVProblem(distribution_fun_test!, 
                                distribution_bc_test!, 
                                y_initial, tspan)
        
    @time BVP.solve(bvp_problem, BVP.MIRK5(); adaptive = false, dt=Float64(L/mesh_size))
    @time BVP.solve(bvp_problem, BVP.MIRK5(); adaptive = false, dt=Float64(L/mesh_size))
end

test_solve()

```

The output of the timing I am getting is:  
` 3.606669 seconds (4.35 M allocations: 216.794 MiB, 1.00% gc time, 96.31% compilation time: 100% of which was recompilation) 0.132779 seconds (440.05 k allocations: 26.994 MiB)`

I am using BoundaryValueDiffEq v5.18.0 and Julia v1.12.

Thanks a lot for your help in advance!  
Max

---

<div class="post-metadata">

**Author:** ![karei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karei/32/214809_2.png) [@karei](https://discourse.julialang.org/u/karei)\
**Post date:** [March 18, 2026, 2:30pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/2 "2026-03-18T14:30:21Z")

</div>

Welcome to the Julia community.

It looks like… um… I think the performance bottleneck is in the `BoundaryValueDiffEq` package (rather than the code you wrote). The type instability is also caused by this package. 🤔

---

<div class="post-metadata">

**Author:** ![MaxSchelski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxschelski/32/221245_2.png) [@MaxSchelski](https://discourse.julialang.org/u/MaxSchelski)\
**Post date:** [March 18, 2026, 9:24pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/3 "2026-03-18T21:24:54Z")

</div>

Thanks! And thanks for your reply!

It’s a pitty that there seems to be nothing I can change in my functions.

Maybe there is a way to optimize how I set up BVProblem instead?  
I tried setting the the parameter nlls to false or true for type stability as suggested in the docs - but this seemed to increase allocations and increased execution time.  
I also tried returning a staticarray for both functions instead of in place changes (I supplied y\_array as a staticarray, too). But this increased allocations massively.

As these now are quite specific points for the boundaryvaluediffeq package - should I post the question somewhere else?

---

<div class="post-metadata">

**Author:** ![jClugstor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jclugstor/32/32689_2.png) [@jClugstor](https://discourse.julialang.org/u/jClugstor)\
**Post date:** [March 18, 2026, 10:46pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/4 "2026-03-18T22:46:30Z")

</div>

You can profile exactly where the allocations are coming from by using `@profview_allocs` (if you’re using VSCode)

---

<div class="post-metadata">

**Author:** ![MaxSchelski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxschelski/32/221245_2.png) [@MaxSchelski](https://discourse.julialang.org/u/MaxSchelski)\
**Post date:** [March 20, 2026, 5:40am UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/5 "2026-03-20T05:40:58Z")

</div>

I am using VSCode, however, for some reason @profview\_allocs did not work for me. I used the alternative PProf instead. But to be honest I couldn’t really find out which other options to test based on the output, as I am not familiar with the package structure of BoundaryValueDiffEq.jl.

It’s a pitty - this Julia implementation is not faster than my previous Python implementation. I expected the performance to be noticeably better in Julia after some optimization.

---

<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:** [March 20, 2026, 6:15am UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/6 "2026-03-20T06:15:44Z")

</div>

BoundaryValueDiffEq.jl is still getting a ton of work, with its core adaptivity algorithms and such just completed last summer. I’ll take a look at some of the performance stuff here. Note that generally the BVP solvers will need to allocate in order to adapt, and in almost all cases you want to have that adaptivity on. But as a smoke test we should get the non-adapting steps to be non-allocating, so I’ll spin up some tests on that to see what’s going on here.

> [@MaxSchelski](#):
>
> As these now are quite specific points for the boundaryvaluediffeq package - should I post the question somewhere else?

This is better as an issuei n the package.

> [@karei](#):
>
> It looks like… um… I think the performance bottleneck is in the `BoundaryValueDiffEq` package (rather than the code you wrote). The type instability is also caused by this package. 🤔

What type instability?

---

<div class="post-metadata">

**Author:** ![karei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karei/32/214809_2.png) [@karei](https://discourse.julialang.org/u/karei)\
**Post date:** [March 20, 2026, 6:55am UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/7 "2026-03-20T06:55:18Z")

</div>

> [@ChrisRackauckas](#):
>
> What type instability?

I found that the return type of both `bvp_problem` and `BVP.solve` is `Any` using Cthulhu’s `@descend`.

```julia-auto
> @descend test_solve()
test_solve() @ Main REPL[5]:1
 1 function test_solve()::Any
 2 L::Core.Const(100.0) = 100.0::Core.Const(100.0)
 3 mesh_size::Core.Const(500) = 500::Core.Const(500)
 4 (tspan::Core.Const((0.0, 100.0))::Tuple{Float64, Float64})::Core.Const(true) = (0.0, Float64(L::Core.Const(100.0))::Core.Const(100.0))::Core.Const((0.0, 100.0))
 6 
 6 (y_initial::Vector{Float64}::Vector{Float64})::Core.Const(true) = [1, (0.001/0.03)::Core.Const(0.03333333333333333), 1, 0.001]::Vector{Float64}
 8 
 8 bvp_problem::Any = BVP.BVProblem::Type{SciMLBase.BVProblem}(distribution_fun_test!::Core.Const(Main.distribution_fun_test!), 
 9 distribution_bc_test!::Core.Const(Main.distribution_bc_test!), 
10 y_initial::Vector{Float64}, tspan::Core.Const((0.0, 100.0)))::Any
11         
12 @time BVP.solve::Core.Const(CommonSolve.solve)(bvp_problem::Any, BVP.MIRK5::Type{BoundaryValueDiffEqMIRK.MIRK5}()::Core.Const(MIRK5(jac_alg = BVPJacobianAlgorithm(), defect_threshold = 0.1, max_num_subintervals = 3000)); adaptive = false, dt=Float64((L::Core.Const(100.0)/mesh_size::Core.Const(500))::Float64)::Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}::NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), <:Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}})::Any
13 @time BVP.solve::Core.Const(CommonSolve.solve)(bvp_problem::Any, BVP.MIRK5::Type{BoundaryValueDiffEqMIRK.MIRK5}()::Core.Const(MIRK5(jac_alg = BVPJacobianAlgorithm(), defect_threshold = 0.1, max_num_subintervals = 3000)); adaptive = false, dt=Float64((L::Core.Const(100.0)/mesh_size::Core.Const(500))::Float64)::Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}::NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), <:Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}})::Any
14 end

```

---

<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:** [March 20, 2026, 7:01am UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/8 "2026-03-20T07:01:59Z")

</div>

> [@karei](#):
>
> und that the return type of both `bvp_problem` and `BVP.solve` is `Any` using Cthulhu’s `@desc`

Can you open an issue for that? That should get addressed.

---

<div class="post-metadata">

**Author:** ![MaxSchelski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxschelski/32/221245_2.png) [@MaxSchelski](https://discourse.julialang.org/u/MaxSchelski)\
**Post date:** [March 23, 2026, 1:52pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/9 "2026-03-23T13:52:04Z")

</div>

Thanks a lot for your reply, Chris. And thanks a lot for developing and maintaining such awesome Julia packages!

Very cool to know that BoundaryValueDiffEq.jl is still being worked on so much.

I just opened an issue.

For my BVP I did find that turning adaptivity on slowed down the solve a bit but did not seem to change the result. I find that I seem to have to set the grid size manually since very small grid sizes lead to inaccurate results - both with “adaptive” turned on or off.

---

<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:** [March 23, 2026, 2:48pm UTC](https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255/10 "2026-03-23T14:48:23Z")

</div>

Yes it’s still a highly active project. It’s the solver library that doesn’t have a paper out yet even, so it’ll be the next “big” SciML solver paper over the next year. The JuliaCon video describes a lot of what was done, so now lots of the algorithm is done but it needs lots of the little bits to complete it. So it needs issues, and then just lots of the little optimizations and bug fixes and interface things.
