# StaticArrays and allocations

**URL:** <https://discourse.julialang.org/t/staticarrays-and-allocations/62123>\
**Category:** General Usage\
**Created:** [May 31, 2021, 10:02am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123 "2021-05-31T10:02:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 31, 2021, 10:02am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/1 "2021-05-31T10:02:58Z")

</div>

Are there are any guarantees when using StaticArrays that the array values will indeed get stack-allocated? Or is it more like a best-effort guarantee and you may still end up with heap-allocated values?

Reason I’m asking is that I’m using StaticArray’s `FieldVector` and see allocations happening when checking with `--track-allocation=user`, e.g.

```julia
- mutable struct vec3 <: FieldVector{3, Float64}
        - x::Float64
        - y::Float64
        - z::Float64
        -     
  4208416 vec3() = new(0, 0, 0)
  5435456 vec3(x, y, z) = new(x, y, z)
        - end

```

I suspect that because I’ve marked the struct as mutable that it still causes heap-allocation?

And in general is what `--track-allocation=user` reports the total bytes in _heap-allocated_ values only? Again, I suspect “allocation” in the context of Julia to mean heap-allocation and not something like `alloca()` in C/C++ which allocates stack space.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [May 31, 2021, 10:36am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/2 "2021-05-31T10:36:11Z")

</div>

> [@paulmelis](#):
>
> Are there are any guarantees when using StaticArrays that the array values will indeed get stack-allocated?

No, Julia does not make any strong guarantees about whether data is allocated on the stack or the heap. In general, immutable objects are very likely to either be stack allocated or only live in registers. This usually does not hold for mutable objects though. There are some cases where allocations of mutable objects can be elided, but in general, Julia’s analysis in this regard is currently not very advanced. This is something that is likely to improve in the future, but you should generally prefer immutable objects, if you can avoid mutation, as this typically allows for more compiler optimizations.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 11:01am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/3 "2021-05-31T11:01:21Z")

</div>

I’m wondering why you want a mutable `FieldVector`?

You can use Setfield.jl/Accessors.jl to update the fields of a regular `struct`

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 31, 2021, 11:04am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/4 "2021-05-31T11:04:51Z")

</div>

I was trying to port some C++ code (and I’m much more comfortable with C++ anyway) and what I was trying to achieve was to have a stack-allocated struct that is still mutable. In C++ it makes sense to have simple values such as 3-vectors of floats on the stack in case they’re frequently created/destroyed, as stack allocation there is cheap and orthogonal to mutability. In Julia those two properties appear to be more intertwined, which takes a bit of getting used to.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 31, 2021, 11:09am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/5 "2021-05-31T11:09:10Z")

</div>

Is `const vec3 = MVector{3, Float64}` an option? That’s what I’m doing (while implementing the Vulkan tutorial, which is originally C++).

Well, technically I’m doing `const Vec{S} = MVector{S, Float64}`, since I don’t like having more than one definition for basically the same thing. You can then use it like `Vec{3}(x, y, z)` and it’ll work and be inlined in arrays etc.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 11:10am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/6 "2021-05-31T11:10:57Z")

</div>

Ah yes, that is easier in C++. We have to hack around immutability a little to get the same result.

Setfield.jl can set the field or equally use setindex! syntax:

```julia
julia> using Setfield

julia> struct Point{T} <: FieldVector{3,T}
           x::T
           y::T
           z::T
       end

julia> p = Point(1, 2, 3)
3-element Point{Int64} with indices SOneTo(3):
 1
 2
 3

julia> @set p[3] = 4
3-element Point{Int64} with indices SOneTo(3):
 1
 2
 4

julia> @set p.y = 7
3-element Point{Int64} with indices SOneTo(3):
 1
 7
 3

```

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 31, 2021, 11:22am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/7 "2021-05-31T11:22:07Z")

</div>

Yuck, so this works even without marking the struct as `mutable`?

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 11:28am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/8 "2021-05-31T11:28:32Z")

</div>

Yeah thats the idea. There are also BangBang.jl and Flatten.jl to do related things with immutables.

ConstructionBase.jl facilitates all this. Some complex types need a custom `ConstructionBase.constructorof` method. Its not the prettiest setup but it works.

---

<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:** [May 31, 2021, 11:47am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/9 "2021-05-31T11:47:18Z")

</div>

> [@Raf](#):
>
> `@set p[3] = 4`

Note that the macro of `Setfield` that “mutates” is `@set!`:

```julia
julia> using StaticArrays

julia> x = @SVector [1,1,1]
3-element SVector{3, Int64} with indices SOneTo(3):
 1
 1
 1

julia> using Setfield

julia> @set x[1] = 2
3-element SVector{3, Int64} with indices SOneTo(3):
 2
 1
 1

julia> x
3-element SVector{3, Int64} with indices SOneTo(3):
 1
 1
 1

julia> @set! x[1] = 2
3-element SVector{3, Int64} with indices SOneTo(3):
 2
 1
 1

julia> x
3-element SVector{3, Int64} with indices SOneTo(3):
 2
 1
 1

```

But, @paulmelis, it is probably useful to think about these immutable objects as single values most of the time. This makes most code very readable. For instance:

```julia
julia> positions = [@SVector rand(3) for i in 1:1000];

julia> velocities = [@SVector rand(3) for i in 1:1000];

julia> function update_positions!(x,v,Δt)
         for i in eachindex(x)
           x[i] = x[i] + v[i]*Δt
         end
       end
update_positions! (generic function with 1 method)

julia> using BenchmarkTools

julia> @btime update_positions!($positions,$velocities,0.1)
  1.300 μs (0 allocations: 0 bytes)

```

Or, even simpler:

```julia
julia> update_positions!(x,v,Δt) = @. x = x + v*Δt
update_positions! (generic function with 1 method)

julia> @btime update_positions!($positions,$velocities,0.1)
  1.198 μs (0 allocations: 0 bytes)

```

which is furthermore slightly faster because `inbounds` is granted.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 11:54am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/10 "2021-05-31T11:54:02Z")

</div>

Neither of them mutate, `@set!` is just a convenience macro to rename the variable.

---

<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:** [May 31, 2021, 11:56am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/11 "2021-05-31T11:56:03Z")

</div>

Sure, but the user experience is different.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 31, 2021, 11:56am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/12 "2021-05-31T11:56:12Z")

</div>

Yes. `immutable`-ness of structs or SVector doesn’t mean that e.g. `+` isn’t defined or that operations with them will allocate (in fact, I’m willing to bet that type stable code with SVectors in it will not allocate, unless you fall back to regular arrays somewhere along the line). It really depends on what you want to do with them - maybe @paulmelis could give use some more information about what they’re trying to do?

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 11:59am UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/13 "2021-05-31T11:59:12Z")

</div>

My point is we shouldn’t suggest that they mutate because the key point for this thread is that they are guaranteed to always live on the stack. Mutables aren’t. I think its better if users know what they do and have a clean mental model.

---

<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:** [May 31, 2021, 12:01pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/14 "2021-05-31T12:01:45Z")

</div>

Agreeing with you, an example to reinforce what you are saying:

```julia
julia> x = @SVector [1,1,1];

julia> f!(x) = @set! x[1] = 2
f! (generic function with 1 method)

julia> f!(x)
3-element SVector{3, Int64} with indices SOneTo(3):
 2
 1
 1

julia> x
3-element SVector{3, Int64} with indices SOneTo(3):
 1
 1
 1

```

They “look” mutable in the scope of the function. But they aren’t.

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 31, 2021, 12:01pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/15 "2021-05-31T12:01:47Z")

</div>

> [@Raf](#):
>
> My point is we shouldn’t suggest that they mutate because the key point for this thread is that they are guaranteed to always live on the stack. Mutables aren’t. I think its better if users know what they do and have a clean mental model.

I’m still not clear for which of the above forms the values are _guaranteed_ to live on the stack? Are there cases where even `SVector` can end up being allocated on the heap?

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 12:22pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/16 "2021-05-31T12:22:25Z")

</div>

> Are there cases where even `SVector` can end up being allocated on the heap?

Yeah I was too strong with “guarantee”, but your Point object will certainly be on the stack, or just registers. I do wonder what circumstances an immutable object would be heap allocated…

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [May 31, 2021, 12:23pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/17 "2021-05-31T12:23:43Z")

</div>

The short answer is none of them are guaranteed to live on the stack (or actually to even live anywhere). One major advantage julia’s compiler has over c/c++ is that it makes far fewer guarantees about how it will implement your code. C and c++ compilers are forced to compile the actual code you wrote more often, even when there was a different way that would have gotten the same algorithm faster. Julia, on the other hand gives itself more room to change the details as long as it can prove you won’t notice the difference. One example of this is that it will often not store `StaticArrays` anywhere in memory, and just use a few registers instead. This is an optimization c won’t often do because for it to be valid, the compiler has to prove that you haven’t done something ugly like take the address of an integer that happens to refer to the memory location of the array.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [May 31, 2021, 12:28pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/18 "2021-05-31T12:28:18Z")

</div>

But this is a good lack of guarantee! don’t we all want our SArrays to just use registers?

The concern about guarantees is heap allocations… is there example of an SArray being heap allocated?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 31, 2021, 2:03pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/19 "2021-05-31T14:03:21Z")

</div>

I think there’s a use for guaranteed stack-allocated, size-known-at-compile-time arrays (possibly from literals only?), though I agree that it’s kind of niche if you get used to not requiring them at all. Certainly requires a different kind of thinking if you’re very used to doing this.

To go into more detail how this could be done would require knowing more about what you’re trying to do/what the code you want to port does, @paulmelis

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 31, 2021, 2:48pm UTC](https://discourse.julialang.org/t/staticarrays-and-allocations/62123/20 "2021-05-31T14:48:40Z")

</div>

> [@Oscar\_Smith](#):
>
> One major advantage julia’s compiler has over c/c++ is that it makes far fewer guarantees about how it will implement your code. C and c++ compilers are forced to compile the actual code you wrote more often, even when there was a different way that would have gotten the same algorithm faster. Julia, on the other hand gives itself more room to change the details as long as it can prove you won’t notice the difference.

This is certainly a double-edged sword. As you get more proficient with C/C++ you will know pretty well when to use stack-allocated versus heap-allocated values and what the performance trade-offs are. So it indeed requires more effort to learn and manage, but overall is pretty transparent as the language mandates a lot of implementation details and the effects of the different types of allocations are somewhat predictable in terms of performance, certainly intuitively. So it also becomes more natural to make those trade-offs yourself to get what you want.

Julia’s handling of how values get allocated might also not be too complex, but the interaction with type-stability and related automatic boxing/unboxing muddies the water a bit it seems. And this is were “to change the details as long as it can prove you won’t notice the difference” comes in, as performance can be greatly influenced by too many allocations, which can be influence by type-instabilities, or by use of SVector versus a normal array, or by `mutable` versus immutable, etc. So before you even get to the clever optimizations that the compiler does it seems there’s a slew of different higher-level choices to be made which are far more important for resulting performance, but which are not really part of the core Julia language. So here the mental modal of e.g. allocations happening in your code appears to be quite a bit more complex. Even though the Julia compiler will do a lot more clever things it also becomes more opaque and less predictable IMO. Case in point are my questions on the StaticArrays types as noted above, but looking at their docs once more I really think no guarantees are given, so the only option is to try them and see what comes out? Btw, all this certainly has to do with far less experience I have with Julia compared to C++.

[Next page](https://discourse.julialang.org/t/staticarrays-and-allocations/62123.md?page=2)
