# Why Are Statically Sized Arrays Immutable?

**URL:** <https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331>\
**Category:** General Usage\
**Tags:** question, staticarrays, immutable\
**Created:** [April 23, 2025, 1:41pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331 "2025-04-23T13:41:20Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 24, 2025, 7:03pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/21 "2025-04-24T19:03:16Z")

</div>

> [@joa-quim](#):
>
> “yes, but it allocates. You should try to avoid that.”

This is usually good advice, but it doesn’t always mean you should completely avoid touching the heap. Sometimes it just means you should avoid _repeated_ allocations and instead allocate reusable containers once before entering the hot loop. A corollary is that in any piece of code for which you care about microbenchmarks (i.e., you’re using BenchmarkTools.jl rather than just `@time`) you should consider taking preallocated memory as an argument, rather than performing heap allocations within that code itself.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [April 24, 2025, 7:08pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/22 "2025-04-24T19:08:25Z")

</div>

I happen to have programmed in the time when the maximum available RAM was \< 640 kB, so I know the value of reusing memory 🙂

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 24, 2025, 7:24pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/23 "2025-04-24T19:24:19Z")

</div>

Great! But I think this is a bit different. We’ve usually got plenty of RAM, so it’s not about avoiding OOM, it’s about not wasting CPU cycles on the allocator/GC in performance sensitive parts of the code. Just sharing my interpretation of the frequent “avoid allocations” admonitions, which I don’t think should be understood as “avoid the heap”.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [April 25, 2025, 12:19am UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/24 "2025-04-25T00:19:18Z")

</div>

> [@joa-quim](#):
>
> But here stack space seems to be treated as infinite and a program that heap allocates seems to be considered a lower quality code.

I think it’s the context and how stack/heap allocations are used in practice. Personal computers in the last couple decades can allocate quite a lot of memory, whereever it is, and Julia is one of the languages that needs a lot to just work (well, we’ll see where juliac goes). People in this world tend to worry about heap allocation or GC latency, which stack allocation doesn’t need to deal with. It’s also generally harder to allocate bigger things on the stack because nobody really wants to do that; the heap allows dynamic sizing and easier sharing across methods. Smaller stack allocations in this context are practically almost free; you’d usually need runaway recursion to hit the limit. Even hefty `SVector`s often don’t crash our systems, it just results in worse performance (compilation, copying).

> [@joa-quim](#):
>
> I happen to have programmed in the time when the maximum available RAM was \< 640 kB

If more people reach these or smaller systems with juliac, I expect stack allocations aren’t going to be perceived as free as they are today, and maybe we’d get some way to profile them on a bigger system.

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [April 25, 2025, 3:58am UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/25 "2025-04-25T03:58:27Z")

</div>

> [@joa-quim](#):
>
> I happen to have programmed in the time when the maximum available RAM was \< 640 kB

Off-topic, but my TRS-80 Model III, purchased in 1980, had 4 KB RAM. I programmed it in Z80 assembler and every byte was precious.

---

<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:** [April 25, 2025, 7:20am UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/26 "2025-04-25T07:20:24Z")

</div>

> [@danielwe](#):
>
> Great! But I think this is a bit different. We’ve usually got plenty of RAM, so it’s not about avoiding OOM, it’s about not wasting CPU cycles on the allocator/GC in performance sensitive parts of the code. Just sharing my interpretation of the frequent “avoid allocations” admonitions, which I don’t think should be understood as “avoid the heap”.

Agreed, plus I’d say it’s more specific than that with Julia. The “avoid allocations” should really be read as “avoid (unexpected) allocations due to type-instabilities”. There’s nothing inherently wrong with having code that does lots of heap-based allocations, as long as you can manually manage them in a way that doesn’t impact performance too much (e.g. in C++ by using pre-allocated pools to reuse blocks, instead of calling `malloc()`/`free()` every time). But type-instability in Julia introduces allocations outside of direct user control. Hence the attention to type-stability to “avoid allocations”, especially _unexpected_ allocations.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 25, 2025, 7:43am UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/27 "2025-04-25T07:43:36Z")

</div>

> [@joa-quim](#):
>
> But stack memory is limited (don’t know its limits)

Related: the second positional, optional, argument to the `Task` constructor, determines the stack size for the created `Task`, when provided:

- [Document `Task(f, n)` API by MilesCranmer · Pull Request #55184 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/55184)

Might be useful for testing (set a low stack size explicitly) or perhaps preventing stack overflows in tricky recursive code. That said, spawning many tasks with an explicitly chosen size, when the size is not very small, is a bad idea, because, as far as I understand, explicitly choosing a stack size is somehow less efficient, causing the stack memory to get eagerly allocated, in contrast to the default behavior. It’s possible I’m not understanding it correctly, though.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 25, 2025, 10:56am UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/28 "2025-04-25T10:56:43Z")

</div>

> [@paulmelis](#):
>
> The “avoid allocations” should really be read as “avoid (unexpected) allocations due to type-instabilities”.

I think the classic ‘avoidable allocation’ issue in Julia is slicing arrays and updating out-of-place when it could be in-place, like for example

```julia
for _ in iter
    A = A[:, :].^2 + A[:, :] * 2
end

```

instead of

```julia
for _ in iter
    A .= A.^2 .+ A .* 2
end

```

---

<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:** [April 25, 2025, 1:32pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/29 "2025-04-25T13:32:52Z")

</div>

> [@DNF](#):
>
> I think the classic ‘avoidable allocation’ issue in Julia is slicing arrays and updating out-of-place when it could be in-place, like for example

Maybe, but that’s relatively easy to find and fix. Some type-instability issues can be quite subtle and unexpected (at first) and annoying to fix, e.g. iterating rows of a DataFrame ([Why DataFrame is not type stable and when it matters | Blog by Bogumił Kamiński](https://bkamins.github.io/julialang/2021/01/08/typestable.html)).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 25, 2025, 2:55pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/30 "2025-04-25T14:55:38Z")

</div>

Sure, but that’s what, in my experience, we are talking about 60% of the time when counseling people to avoid allocations, was my point.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 25, 2025, 3:06pm UTC](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331/31 "2025-04-25T15:06:20Z")

</div>

> [@paulmelis](#):
>
> The “avoid allocations” should really be read as “avoid (unexpected) allocations due to type-instabilities”.

Type instability is important, but it’s a separate point from the usual admonitions to avoid allocations, which refer to things like creating new arrays in every iteration of a performance-sensitive loop. This can be completely type stable and still greatly harm performance.

(That said, I agree that the hunt for allocations can help people find and fix type instabilities because dynamic dispatch shows up in benchmarks as a tiny box allocation. But I’d consider that a happy side effect of avoiding allocations, rather than the main reason people advocate it.)

[Previous page](https://discourse.julialang.org/t/why-are-statically-sized-arrays-immutable/128331.md?page=1)
