# Strange memory allocations

**URL:** <https://discourse.julialang.org/t/strange-memory-allocations/95203>\
**Category:** General Usage\
**Tags:** performance\
**Created:** [February 25, 2023, 8:11pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203 "2023-02-25T20:11:40Z")\
**Posts on this page:** 8\
**Page:** 1

<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:** [February 25, 2023, 8:11pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/1 "2023-02-25T20:11:40Z")

</div>

I have the following function:

```julia
function residual!(res, yd, y::MVector{S, SimFloat}, s::KPS3, time) where S
    if false
        T = S-2 # T: three times the number of particles excluding the origin
        segments = div(T,6) - KITE_PARTICLES
        # unpack the vectors y and yd
        # extract the data for the winch simulation
        length, v_reel_out = y[end-1], y[end]
        lengthd, v_reel_outd = yd[end-1], yd[end]
        # extract the data of the particles
        y_ = @view y[1:end-2]
        yd_ = @view yd[1:end-2]
        # unpack the vectors y and yd
        part = reshape(SVector{T}(y_), Size(3, div(T,6), 2))
        partd = reshape(SVector{T}(yd_), Size(3, div(T,6), 2))
    # pos1 = part[:,:,1]
    # pos1, vel1 = part[:,:,1], part[:,:,2]
    # pos = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1[:,i-1]) end for i in 1:div(T,6)+1)
    # vel = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1[:,i-1]) end for i in 1:div(T,6)+1)
    # posd1, veld1 = partd[:,:,1], partd[:,:,2]
    # posd = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1[:,i-1]) end for i in 1:div(T,6)+1)
    # veld = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1[:,i-1]) end for i in 1:div(T,6)+1)
    else
        part = reshape(SVector{S}(y), Size(3, div(S,6), 2))
        partd = reshape(SVector{S}(yd), Size(3, div(S,6), 2))
        pos1, vel1 = part[:,:,1], part[:,:,2]
        pos = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1[:,i-1]) end for i in 1:div(S,6)+1)
        vel = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1[:,i-1]) end for i in 1:div(S,6)+1)
        posd1, veld1 = partd[:,:,1], partd[:,:,2]
        posd = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1[:,i-1]) end for i in 1:div(S,6)+1)
        veld = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1[:,i-1]) end for i in 1:div(S,6)+1)
    end

    # update parameters
    pos_kite = pos[div(S,6)+1]
    s.vel_kite .= vel[div(S,6)+1]
    delta_t = time - s.t_0
    delta_v = s.v_reel_out - s.last_v_reel_out
    s.segment_length = (s.l_tether + s.last_v_reel_out * delta_t + 0.5 * delta_v * delta_t^2) / div(S,6)
    s.c_spring = s.set.c_spring / s.segment_length
    s.damping = s.set.damping / s.segment_length
    s.beta = calc_elevation(s)

    # call core calculation routines
    vec_c = SVector{3, SimFloat}(pos[s.set.segments] - pos_kite) # convert to SVector to avoid allocations
    v_app = SVector{3, SimFloat}(s.v_wind - s.vel_kite)
    calc_set_cl_cd!(s, vec_c, v_app)
    calc_aero_forces(s, pos_kite, s.vel_kite, s.rho, s.steering) # force at the kite
    loop(s, pos, vel, posd, veld, s.res1, s.res2)
  
    # copy and flatten result
    for i in 2:div(S,6)+1
        for j in 1:3
           @inbounds res[3*(i-2)+j] = s.res1[i][j]
           @inbounds res[3*(div(S,6))+3*(i-2)+j] = s.res2[i][j]
        end
    end
    if norm(res) < 1e5
        # println(norm(res))
        for i in eachindex(pos)
            @inbounds s.pos[i] .= pos[i]
        end
    end
    # @assert ! isnan(norm(res))
    s.iter += 1
    nothing
end

```

It does not allocate any memory. If I uncomment the line `# pos1 = part[:,:,1]` it suddenly allocates a lot of memory, even though this part of the code is never executed. How can that happen?

The full test can be found here: [KiteModels.jl/bench3.jl at main · ufechner7/KiteModels.jl · GitHub](https://github.com/ufechner7/KiteModels.jl/blob/main/test/bench3.jl)

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [February 25, 2023, 8:54pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/3 "2023-02-25T20:54:22Z")

</div>

Does the uncommenting make it type unstable? What does `@code_warntype` say?

---

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [February 25, 2023, 9:14pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/4 "2023-02-25T21:14:58Z")

</div>

Is getindex of SVector non-allocating?

---

<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:** [February 26, 2023, 12:31pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/5 "2023-02-26T12:31:05Z")

</div>

Simplified test case:

```julia
using StaticArrays, LinearAlgebra

const KVec3 = MVector{3, Float64}

Base.@kwdef mutable struct KPS3{S, T, P}
    v_apparent::T = zeros(S, 3)
end

const kps3= KPS3{Float64, KVec3, 6+4+1}()
const KITE_PARTICLES = 4

const WINCH = false

function residual!(res, yd, y::MVector{S, Float64}, s::KPS3, time) where S
    if WINCH
        T = S-2 # T: three times the number of particles excluding the origin
        segments = div(T,6) - KITE_PARTICLES
        length, v_reel_out = y[end-1], y[end]
        lengthd, v_reel_outd = yd[end-1], yd[end]
        # extract the data of the particles
        y_ = @view y[1:end-2]
        yd_ = @view yd[1:end-2]
        part = reshape(SVector{T}(y_), Size(3, div(T,6), 2))
        partd = reshape(SVector{T}(yd_), Size(3, div(T,6), 2))
        # if you comment the following line there are no allocations
        pos1 = part[:,:,1]
    else
        part = reshape(SVector{S}(y), Size(3, div(S,6), 2))
        partd = reshape(SVector{S}(yd), Size(3, div(S,6), 2))
        pos1, vel1 = part[:,:,1], part[:,:,2]
        pos = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1[:,i-1]) end for i in 1:div(S,6)+1)
        vel = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1[:,i-1]) end for i in 1:div(S,6)+1)
        posd1, veld1 = partd[:,:,1], partd[:,:,2]
        posd = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1[:,i-1]) end for i in 1:div(S,6)+1)
        veld = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1[:,i-1]) end for i in 1:div(S,6)+1)
    end
    nothing
end

function test_residual()
    if WINCH
        y0 = MVector{62, Float64}([13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 150.0, 0.0])
        yd0= MVector{62, Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0])
    else
        y0 = MVector{60, Float64}([13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
        yd0= MVector{60, Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81])
    end
    time = 0.1
    res1 = zeros(SVector{6, KVec3})
    res2 = deepcopy(res1)
    res = reduce(vcat, vcat(res1, res2))
    # call first time to compile
    residual!(res, yd0, y0, kps3, time)
    # measure allocations
    @allocated residual!(res, yd0, y0, kps3, time)
end

test_residual()

```

This shows 1728 allocation which disappear if I comment the line `pos1 = part[:,:,1]` .

The allocations also disappear if I use `WINCH=true`.

So all works fine if I execute the code that I want to execute with the correct sized array as input.

It allocates if there is dead code inside an `if false; ...; end` block that would operate on a wrongly sized array if executed.

Not sure if this is a bug…

---

<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:** [February 26, 2023, 12:34pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/6 "2023-02-26T12:34:45Z")

</div>

```julia
julia> @code_warntype test_residual()
MethodInstance for test_residual()
  from test_residual() in Main at /home/ufechner/repos/KiteModels/test/test_residual2.jl:40
Arguments
  #self#::Core.Const(test_residual)
Locals
  b1::Base.RefValue{Int64}
  b0::Base.RefValue{Int64}
  res::MVector{36, Float64}
  res2::SVector{6, MVector{3, Float64}}
  res1::SVector{6, MVector{3, Float64}}
  time::Float64
  yd0::MVector{60, Float64}
  y0::MVector{60, Float64}
Body::Int64
1 ─ Core.NewvarNode(:(b1))
│ Core.NewvarNode(:(b0))
│ Core.NewvarNode(:(res))
│ Core.NewvarNode(:(res2))
│ Core.NewvarNode(:(res1))
│ Core.NewvarNode(:(time))
│ Core.NewvarNode(:(yd0))
│ Core.NewvarNode(:(y0))
└── goto #3 if not Main.WINCH
2 ─ Core.Const(:(Core.apply_type(Main.MVector, 62, Main.Float64)))
│ Core.Const(:(Base.vect(13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 150.0, 0.0)))
│ Core.Const(:(y0 = (%10)(%11)))
│ Core.Const(:(Core.apply_type(Main.MVector, 62, Main.Float64)))
│ Core.Const(:(Base.vect(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0)))
│ Core.Const(:(yd0 = (%13)(%14)))
└── Core.Const(:(goto %23))
3 ┄ %17 = Core.apply_type(Main.MVector, 60, Main.Float64)::Core.Const(MVector{60, Float64})
│ %18 = Base.vect(13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)::Vector{Float64}
│ (y0 = (%17)(%18))
│ %20 = Core.apply_type(Main.MVector, 60, Main.Float64)::Core.Const(MVector{60, Float64})
│ %21 = Base.vect(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81)::Vector{Float64}
│ (yd0 = (%20)(%21))
│ (time = 0.1)
│ %24 = Core.apply_type(Main.SVector, 6, Main.KVec3)::Core.Const(SVector{6, MVector{3, Float64}})
│ (res1 = Main.zeros(%24))
│ (res2 = Main.deepcopy(res1))
│ %27 = Main.vcat(res1, res2)::SVector{12, MVector{3, Float64}}
│ (res = Main.reduce(Main.vcat, %27))
│ Main.residual!(res, yd0, y0, Main.kps3, time::Core.Const(0.1))
│ $(Expr(:meta, :force_compile))
│ %31 = Core.apply_type(Base.Ref, Base.Int64)::Core.Const(Ref{Int64})
│ (b0 = (%31)(0))
│ %33 = Core.apply_type(Base.Ref, Base.Int64)::Core.Const(Ref{Int64})
│ (b1 = (%33)(0))
│ Base.gc_bytes(b0)
│ Main.residual!(res, yd0, y0, Main.kps3, time::Core.Const(0.1))
│ Base.gc_bytes(b1)
│ %38 = Base.getindex(b1)::Int64
│ %39 = Base.getindex(b0)::Int64
│ %40 = (%38 - %39)::Int64
└── return %40

```

I would not know what to look for, though…

Its a bit annoying in the sense that I cannot execute different branches of my code depending on a constant without causing allocations…

---

<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:** [February 26, 2023, 12:51pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/7 "2023-02-26T12:51:56Z")

</div>

Created a bug report: [Dead code is causing memory allocations · Issue #48798 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/48798)

---

<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:** [February 26, 2023, 10:54pm UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/8 "2023-02-26T22:54:24Z")

</div>

OK, this is a duplicate of [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276) .

Their is an easy workaround: Just rename some of the variables that appear in both branches of the code:

```julia
using StaticArrays, LinearAlgebra

const KVec3 = MVector{3, Float64}

Base.@kwdef mutable struct KPS3{S, T, P}
    v_apparent::T = zeros(S, 3)
end

const kps3= KPS3{Float64, KVec3, 6+4+1}()
const KITE_PARTICLES = 4

const WINCH = false

function residual!(res, yd, y::MVector{S, Float64}, s::KPS3, time) where S
    if WINCH
        T = S-2 # T: three times the number of particles excluding the origin
        segments = div(T,6) - KITE_PARTICLES
        length, v_reel_out = y[end-1], y[end]
        lengthd, v_reel_outd = yd[end-1], yd[end]
        # extract the data of the particles
        y_ = @view y[1:end-2]
        yd_ = @view yd[1:end-2]
        part = reshape(SVector{T}(y_), Size(3, div(T,6), 2))
        partd = reshape(SVector{T}(yd_), Size(3, div(T,6), 2))
        # if you comment the following line there are no allocations
        pos1_, vel1_ = part[:,:,1], part[:,:,2]
        pos = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1_[:,i-1]) end for i in 1:div(T,6)+1)
        vel = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1_[:,i-1]) end for i in 1:div(T,6)+1)
        posd1_, veld1_ = partd[:,:,1], partd[:,:,2]
        posd = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1_[:,i-1]) end for i in 1:div(T,6)+1)
        veld = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1_[:,i-1]) end for i in 1:div(T,6)+1)
    else
        part = reshape(SVector{S}(y), Size(3, div(S,6), 2))
        partd = reshape(SVector{S}(yd), Size(3, div(S,6), 2))
        pos1, vel1 = part[:,:,1], part[:,:,2]
        pos = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1[:,i-1]) end for i in 1:div(S,6)+1)
        vel = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1[:,i-1]) end for i in 1:div(S,6)+1)
        posd1, veld1 = partd[:,:,1], partd[:,:,2]
        posd = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1[:,i-1]) end for i in 1:div(S,6)+1)
        veld = SVector{div(S,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1[:,i-1]) end for i in 1:div(S,6)+1)
    end
    nothing
end

function test_residual()
    if WINCH
        y0 = MVector{62, Float64}([13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 150.0, 0.0])
        yd0= MVector{62, Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0])
    else
        y0 = MVector{60, Float64}([13.970413450119487, 0.0, 21.238692070636343, 27.65581376097752, 0.0, 42.66213714321849, 40.976226230518435, 0.0, 64.314401166278, 53.87184032029182, 0.0, 86.22231803750196, 66.28915240374937, 0.0, 108.4048292516046, 78.17713830204762, 0.0, 130.87545423106485, 79.56930502428155, 0.0, 135.70836376062155, 80.90383289255747, 0.0, 137.7696816741141, 80.60126812407692, 2.4016533873456325, 135.3023287520457, 80.60126812407692, -2.4016533873456325, 135.3023287520457, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
        yd0= MVector{60, Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81, 0.0, 0.0, -9.81])
    end
    time = 0.1
    res1 = zeros(SVector{6, KVec3})
    res2 = deepcopy(res1)
    res = reduce(vcat, vcat(res1, res2))
    # call first time to compile
    residual!(res, yd0, y0, kps3, time)
    # measure allocations
    @allocated residual!(res, yd0, y0, kps3, time)
end

test_residual()

```

I had to rename `pos1, vel1, posd1, veld1` to `pos1_, vel1_, posd1_, veld1_` to avoid any memory allocations.

Still not clear to me: Why these 4 variables and not any others…

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 27, 2023, 2:12am UTC](https://discourse.julialang.org/t/strange-memory-allocations/95203/9 "2023-02-27T02:12:10Z")

</div>

> [@ufechner7](#):
>
> Why these 4 variables and not any others

Because these four variables are captured by closures which are created by the generator expressions.

To illustrate:

```julia
julia> function gengen()
           a = if true; 1 else 1 end
           if true; b=1 else b=1 end
           return (a+x for x in 1:5), (b+x for x in 1:5)
       end
gengen (generic function with 1 method)

julia> g1, g2 = gengen()
       g1.f.a, g2.f.b
(1, Core.Box(1))

julia> g1..., g2...
(2, 3, 4, 5, 6, 2, 3, 4, 5, 6)

julia> g2.f.b.contents = 11
       g1..., g2...
(2, 3, 4, 5, 6, 12, 13, 14, 15, 16)

```

The rule is currently very (too) simple: if a local variable _identifier_ is syntactically assigned more than once, or if it’s assigned in a conditional, and if it is captured by a closure, then it is boxed. It leads to a lot of unnecessary boxing. And boxes are currently very (too) simple: they expressly lose type information. It leads to a lot of unnecessarily slow code, and is a bug that must be fixed before Julia can be considered a serious language imo.
