# Allocations when pushing to SVector in a loop

**URL:** <https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472>\
**Category:** General Usage\
**Created:** [February 5, 2019, 1:55pm UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472 "2019-02-05T13:55:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rjww](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rjww/32/6988_2.png) [@rjww](https://discourse.julialang.org/u/rjww)\
**Post date:** [February 5, 2019, 1:55pm UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472/1 "2019-02-05T13:55:06Z")

</div>

I’m trying to use `SVector`s from [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) to minimise allocations in a piece of code, but seeing some weird behaviour (and extra allocations) in a specific use case. If I call the following function

```julia
function foo()
    v = SVector{0,Int64}()
    v = push(v, 0)
end

```

`@btime` returns `1.815 ns (0 allocations: 0 bytes)`. As expected, everything is done on the stack. But if I push to the `SVector` in a loop, like so

```julia
function bar()
    v = SVector{0,Int64}()
    for i in 1:10
        v = push(v, i)
    end
end

```

then I end up with `233.220 ns (10 allocations: 560 bytes)`. Can anyone tell me what’s going on here?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 5, 2019, 2:13pm UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472/2 "2019-02-05T14:13:24Z")

</div>

See [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/index.html#Write-%22type-stable%22-functions-1)

`v` changes type in every iteration.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [February 5, 2019, 2:50pm UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472/3 "2019-02-05T14:50:54Z")

</div>

To elaborate a bit on @kristoffer.carlsson’s answer, consider:

```julia
julia> v = SVector{0, Int64}()
0-element SArray{Tuple{0},Int64,1,0}

julia> push(v, 0)
1-element SArray{Tuple{1},Int64,1,1}:
 0

```

One way around this is to use mutable `MArrays`:

```julia
function bar()
    v = zeros(MVector{10})
    for i ∈ 1:10
        v[i] = i
    end
end

julia> @btime bar()
  1.640 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![rjww](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rjww/32/6988_2.png) [@rjww](https://discourse.julialang.org/u/rjww)\
**Post date:** [February 6, 2019, 1:44am UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472/4 "2019-02-06T01:44:57Z")

</div>

Thanks @kristoffer.carlsson and @nilshg, that makes sense. Why the allocations though? I understand that using an immutable `SVector` would be inefficient, but how does the type instability result in the assignment allocating to the heap when, e.g., both `SVector{0,Int64}` and `SVector{1,Int64}` exist on the stack?

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 6, 2019, 4:54am UTC](https://discourse.julialang.org/t/allocations-when-pushing-to-svector-in-a-loop/20472/5 "2019-02-06T04:54:32Z")

</div>

> both `SVector{0,Int64}` and `SVector{1,Int64}` exist on the stack

There’s nothing special about `SVector` which guarantees that it’s allocated on the stack. The elements commonly exist only in registers (for type stable code with short SVectors), or in a heap allocated “box”, for type unstable code. The detail of what storage is used is entirely up to the compiler.

You can see what’s happening with `@code_warntype`: note the several occurrences of `Any`. This means the compiler can’t figure out the type of this value at compile time, and will resort to putting the value on the heap next to its runtime type information.

```julia
julia> function bar()
           v = SVector{0,Int64}()
           for i in 1:10
               v = push(v, i)
           end
           v
       end
bar (generic function with 1 method)

julia> @code_warntype bar()
Body::Any
1 ─ goto #7 if not true
2 ┄ %2 = φ (#1 => $(QuoteNode(Int64[])), #6 => %5)::Any
│ %3 = φ (#1 => 1, #6 => %11)::Int64
│ %4 = φ (#1 => 1, #6 => %12)::Int64
│ %5 = (Main.push)(%2, %3)::Any
│ %6 = (%4 === 10)::Bool
└── goto #4 if not %6
3 ─ goto #5
4 ─ %9 = (Base.add_int)(%4, 1)::Int64
└── goto #5
5 ┄ %11 = φ (#4 => %9)::Int64
│ %12 = φ (#4 => %9)::Int64
│ %13 = φ (#3 => true, #4 => false)::Bool
│ %14 = (Base.not_int)(%13)::Bool
└── goto #7 if not %14
6 ─ goto #2
7 ┄ %17 = φ (#5 => %5, #1 => $(QuoteNode(Int64[])))::Any
└── return %17

```
