# StructArrays.jl getindex cost memory

**URL:** <https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853>\
**Category:** Performance\
**Tags:** question\
**Created:** [February 13, 2025, 8:04am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853 "2025-02-13T08:04:59Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![kongdd](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kongdd/32/17058_2.png) [@kongdd](https://discourse.julialang.org/u/kongdd)\
**Post date:** [February 13, 2025, 8:04am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853/1 "2025-02-13T08:04:59Z")

</div>

```julia
using StructArrays
using BenchmarkTools

abstract type AbstractSoilParam{T} end

@kwdef mutable struct ParamCampbell{T} <: AbstractSoilParam{T}
  θ_sat::T = 0.287 # [m3 m-3]
  # θ_res::T = 0.075 # [m3 m-3]
  ψ_sat::T = -10.0 # [cm]
  Ksat::T = 34 / 3600 # [cm s-1]
  b::T = 4.0 # [-]
end

mutable struct SoilParam{T}
  par::StructVector{ParamCampbell{T}} # multiple layers
end

begin
  N = 10
  θ_sat = fill(0.287, N) # [m3 m-3]
  ψ_sat = fill(-10.0, N) # [cm]
  Ksat = fill(34 / 3600, N) # [cm s-1]
  b = fill(4.0, N)
  par = StructVector{ParamCampbell{Float64}}((θ_sat, ψ_sat, Ksat, b))
  param = SoilParam{Float64}(par)
end

function test_param(param::SoilParam{Float64}, N::Int)
  @inbounds for k in 1:10_000
    for i in 1:N
      _par = param.par[i]
    end
  end
end

```

```julia
julia> @btime test_param($param, N)
  2.558 ms (100000 allocations: 4.58 MiB)

```

Any idea how to fix this?

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [February 13, 2025, 8:14am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853/2 "2025-02-13T08:14:11Z")

</div>

> [@kongdd](#):
>
> ```julia
> @kwdef mutable struct ParamCampbell{T} <: AbstractSoilParam{T}
> θ_sat::T = 0.287 # [m3 m-3]
> # θ_res::T = 0.075 # [m3 m-3]
> ψ_sat::T = -10.0 # [cm]
> Ksat::T = 34 / 3600 # [cm s-1]
> b::T = 4.0 # [-]
> end
> 
> ```

If you’re going to use `StructVector` you don’t need `ParamCampbell` to be `mutable struct`. When you index the vector, it creates a struct which allocates, as Julia cannot yet get rid of it.

Simply defining it as `struct` should fix the allocations.

---

<div class="post-metadata">

**Author:** ![kongdd](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kongdd/32/17058_2.png) [@kongdd](https://discourse.julialang.org/u/kongdd)\
**Post date:** [February 13, 2025, 8:19am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853/3 "2025-02-13T08:19:42Z")

</div>

Just tried. Remove `mutable` not work.

This one works:

```julia
function solution(par::StructVector{ParamCampbell{T}}, N::Int) where {T<:Real}
  @inbounds for k in 1:10_000
    for i in 1:N
      _par = par[i]
    end
  end
end
@btime solution($par, N)
# 3.200 ns (0 allocations: 0 bytes)

```

But have no idea why `test_param` not.

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [February 13, 2025, 9:03am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853/4 "2025-02-13T09:03:18Z")

</div>

It seems that, in this case, Julia simply compiles it to an empty function, thus not allocating. I’m not sure why indexing causes allocations.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 13, 2025, 10:12am UTC](https://discourse.julialang.org/t/structarrays-jl-getindex-cost-memory/125853/5 "2025-02-13T10:12:04Z")

</div>

> [@kongdd](#):
>
> ```julia
> mutable struct SoilParam{T}
> par::StructVector{ParamCampbell{T}} # multiple layers
> end
> 
> ```

The problem is that `StructVector{ParamCampbell{T}}` is not a concrete type, since `StructVector` needs more type parameters to be fully specified.

You could write

```julia
struct SoilParam{T, SV <: StructVector{ParamCampbell{T}}}
  par::SV
end

```

instead.
