# How To Avoiding Allocations in Static Structs

**URL:** <https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196>\
**Category:** Performance\
**Tags:** array, memory-allocation, struct\
**Created:** [December 3, 2022, 11:09pm UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196 "2022-12-03T23:09:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cdelv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cdelv/32/44851_2.png) [@cdelv](https://discourse.julialang.org/u/cdelv)\
**Post date:** [December 3, 2022, 11:09pm UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196/1 "2022-12-03T23:09:31Z")

</div>

Hi, I’m doing an MD simulation and have a problem getting good performance with static structs. The idea is to have a struct that represents a particle. I checked that using static structs is the fastest (nice) way of doing it, even if I have to override the particle when editing a field. I have the following implementation inspired by [AtomsBase.jl](https://github.com/JuliaMolSim/AtomsBase.jl).

```julia
using StaticArrays

struct Particle{D}
    r::SVector{D, Float64} 
    v::SVector{D, Float64}
    a::SVector{D, Float64}
    m::Float64
end

```

This works great. But I have a lot of questions about the workflow. For example, I can make a function that edits a field, for example

```julia
function Set_r(P::Particle{D}, r::SVector{D, Float64})::Particle{D} where D
    Particle(r,P.v,P.a,P.m,P.rad)
end

@btime Set_r(P, SVector(0.0,0.0,0.0))
3.370 ns (0 allocations: 0 bytes)

```

This works similar with all the vectors, but when I do it for the mass

```julia
function Set_m(P::Particle{D}, m::Float64)::Particle{D} where D
    Particle(P.r,P.v,P.a,m,P.rad)
end

@btime Set_m(P,0.0)
20.917 ns (1 allocation: 96 bytes)

```

This, for me, is very weird. Why a scalar would have 1 allocation and a vector of 3 scalars won’t? Also, if I wore to add fields to the struct, suddenly the set methods will become very cumbersome to work with. Is there another way to improve this workflow?

At last, the idea is to have a vector of structs to run the simulation. Therefore I’ll be overriding the particles of the vector each time I have to update the position (for example). Is there a way to avoid allocations while doing this? What is the best way of doing this sort of thing?

```julia
@btime particles[1] = Set_r(P,SVector(0.0,0.0,0.0))
@btime particles[2] = Set_m(P,0.0)
  20.628 ns (1 allocation: 96 bytes)
  27.820 ns (1 allocation: 96 bytes)

```

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [December 4, 2022, 12:04am UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196/2 "2022-12-04T00:04:12Z")

</div>

I can’t reproduce it:

```julia
julia> using StaticArrays

julia> struct Particle{D}
           r::SVector{D, Float64}
           v::SVector{D, Float64}
           a::SVector{D, Float64}
           m::Float64
       end

julia> function Set_r(P::Particle{D}, r::SVector{D, Float64})::Particle{D} where D
           Particle(r,P.v,P.a,P.m)
       end;

julia> function Set_m(P::Particle{D}, m::Float64)::Particle{D} where D
           Particle(P.r,P.v,P.a,m)
       end;

julia> const P = Particle(rand(SVector{3}), rand(SVector{3}), rand(SVector{3}), rand());

julia> @btime Set_r(P, SVector(0.0,0.0,0.0));
  1.207 ns (0 allocations: 0 bytes)

julia> @btime Set_m(P, 0.0);
  1.207 ns (0 allocations: 0 bytes)

```

Perhaps you were using a non-const global `P`?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 4, 2022, 12:15am UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196/3 "2022-12-04T00:15:33Z")

</div>

> [@cdelv](#):
>
> ```julia
> @btime Set_m(P,0.0)
> 20.917 ns (1 allocation: 96 bytes)
> 
> ```

I can’t reproduce it either, but in any case to properly benchmark you need to interpolate the variables, i. e., use `@btime Set_m($P,0.0)`, with the `$`. I would bet that solves your problem.

For example, I don´t get the allocations, but the benchmark is quite different:

```julia
julia> @btime particles[1] = Set_r(P,SVector(0.0,0.0,0.0));
  15.816 ns (0 allocations: 0 bytes)

julia> @btime $particles[1] = Set_r($P,SVector(0.0,0.0,0.0))
  3.898 ns (0 allocations: 0 bytes)

```

(as a side note, if you are doing particle simulations, take a look at [CellListMap](https://github.com/m3g/CellListMap.jl) :-), might be useful)

---

<div class="post-metadata">

**Author:** ![cdelv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cdelv/32/44851_2.png) [@cdelv](https://discourse.julialang.org/u/cdelv)\
**Post date:** [December 4, 2022, 12:31am UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196/4 "2022-12-04T00:31:24Z")

</div>

Thanks, @fredrikekre, and @lmiq. It’s weird that the benchmark is so different but in fact, I was using a non-const P. I think the reason is that I was using a Jupyter notebook to test things on the fly. But somehow it calms me a bit to know that code works like I thought it should.

I made some research about array management and may help someone in the future with the same problem. I stumbled across [StructArrays.jl](https://github.com/JuliaArrays/StructArrays.jl). I found that makes management very easy. Also, a time step would look like this

```julia
aos = [P for i = 1:400]
soa = StructArray(aos);

r = soa.r + soa.v*0.1
@btime map((x,y) -> x.r = y, LazyRows(soa), r)
1.699 μs (4 allocations: 9.67 KiB)

```

which is 75 times faster in my notebook than doing it in a for loop and only does 8 allocations. Impressive!

@lmiq I feel honored that you answered my question, I love your package, it’s great. I was planning to add CellListMap to the simulation.

---

<div class="post-metadata">

**Author:** ![sfuerst](https://avatars.discourse-cdn.com/v4/letter/s/3da27b/32.png) [@sfuerst](https://discourse.julialang.org/u/sfuerst)\
**Post date:** [December 5, 2022, 4:48pm UTC](https://discourse.julialang.org/t/how-to-avoiding-allocations-in-static-structs/91196/5 "2022-12-05T16:48:08Z")

</div>

Regarding the workflow you could also take a look at [Accessors.jl](https://github.com/JuliaObjects/Accessors.jl)
