# Allocation with StaticArrays

**URL:** <https://discourse.julialang.org/t/allocation-with-staticarrays/68176>\
**Category:** New to Julia\
**Tags:** memory-allocation, staticarrays\
**Created:** [September 14, 2021, 10:06pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176 "2021-09-14T22:06:32Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 14, 2021, 10:06pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/1 "2021-09-14T22:06:32Z")

</div>

Hi,  
I thought I got better at this, but there’s a function that’s creating allocations and I can’t figure out why. I’ve spent a few hours troubleshooting this with no success. Here’s the function:

```julia
using StaticArrays
function transformPoint(point,transformationMatrix)
    homogeneousPoint = SA_F64[point[1],point[2],point[3],1.0];
    homogeneousPoint = transformationMatrix*homogeneousPoint;
    return SA_F64[homogeneousPoint[1],homogeneousPoint[2],homogeneousPoint[3]];
end

```

where the inputs are a SVector of length 3 and a 4x4 SMatrix. For instance:

```julia
point=SA_F64[1,2,3];
transformationMatrix=SA_F64[1 2 3 4; 5 6 7 8; 1 2 3 4; 5 6 7 8];

```

Any hints as to why this is allocating?  
Thanks a lot!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [September 14, 2021, 10:12pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/2 "2021-09-14T22:12:34Z")

</div>

> [@Ribeiro](#):
>
> Any hints as to why this is allocating?

As far as I can tell, it isn’t:

```julia
julia> @btime transformPoint($point, $transformationMatrix)
  0.017 ns (0 allocations: 0 bytes)
3-element SVector{3, Float64} with indices SOneTo(3):
 18.0
 46.0
 18.0

```

Note that the sub-nanosecond timing means that the compiler has optimized away the entire function, which is pretty neat. We can avoid that by hiding the input behind a Ref:

```julia
julia> @btime transformPoint(x[], $transformationMatrix) setup=(x = Ref($point))
  1.500 ns (0 allocations: 0 bytes)

```

---

<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:** [September 14, 2021, 10:30pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/3 "2021-09-14T22:30:52Z")

</div>

> [@Ribeiro](#):
>
> ```julia
> function transformPoint(point,transformationMatrix)
> homogeneousPoint = SA_F64[point[1],point[2],point[3],1.0];
> homogeneousPoint = transformationMatrix*homogeneousPoint;
> return SA_F64[homogeneousPoint[1],homogeneousPoint[2],homogeneousPoint[3]];
> end
> 
> ```

You can write this simpler and more general:

```julia
function transform(p, M) 
    p1 = push(p, one(eltype(p)) # push(p, true) could work too
    return pop(M * p1) 
end

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [September 14, 2021, 10:34pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/4 "2021-09-14T22:34:56Z")

</div>

Maybe one could also simplify the expressions by using splatting:  
`homogeneousPoint = SA_F64[point...,1.0]`  
and:  
`return SA_F64[homogeneousPoint[1:3]...]`

---

<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:** [September 14, 2021, 10:39pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/5 "2021-09-14T22:39:53Z")

</div>

> [@rafael.guerra](#):
>
> SA\_F64[homogeneousPoint[1:3]…]

I’m skeptical that this works, did you test it? `1:3` does not tell the compiler about size.

One could use `p[SOneTo(3)]`, but `pop` is more general in just removing the last element.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [September 14, 2021, 10:41pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/6 "2021-09-14T22:41:17Z")

</div>

It seems to work but it allocates, while the first splatting does not allocate.

Writing the return as follows with views does not allocate:  
`return @views SVector{3,Float64}(homogeneousPoint[1:3])`

Is there any shorter way of writing it?

---

<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:** [September 14, 2021, 11:24pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/7 "2021-09-14T23:24:22Z")

</div>

> [@rafael.guerra](#):
>
> `return @views SVector{3,Float64}(homogeneousPoint[1:3])`
> 
> Is there any shorter way of writing it?

Not shorter, but more general:

```julia
SVector{N, Float64}(ntuple(i->v[i],N)...)

```

I’ve been using this pattern, but I like the suggestion of @DNF of using push and pop in some cases.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [September 14, 2021, 11:26pm UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/8 "2021-09-14T23:26:19Z")

</div>

Thanks, `pop` seems to be the simplest by far and the whole shebang could have been written as:  
`transformPoint(p, M) = pop(M * SA_F64[p...,1.0])`

---

<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:** [September 15, 2021, 4:29am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/9 "2021-09-15T04:29:10Z")

</div>

> [@rafael.guerra](#):
>
> `return @views SVector{3,Float64}(homogeneousPoint[1:3])`
> 
> Is there any shorter way of writing it?

`return homogeneousPoint(SOneTo(3))`

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 7:24am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/10 "2021-09-15T07:24:06Z")

</div>

> [@rdeits](#):
>
> As far as I can tell, it isn’t:

Yeah, when I first wrote the function and tested it in isolation, it wasn’t. But when I run it within another function I get allocations.  
I’m having a hard time reproducing it, but this seems to do it:

```julia
p1=SA_F64[1,2,3];
p2=SA_F64[1,2,3];
p3=SA_F64[1,2,3];
function tmp(p1,p2,p3,M)
       p1=transformPoint(p1,M)
       p2=transformPoint(p2,M)
       p3=transformPoint(p3,M)
       return p1,p2,p3
end
M=SA_F64[1 2 3 4; 5 6 7 8; 1 2 3 4; 5 6 7 8];

@time p1,p2,p3=tmp(p1,p2,p3,M)
  0.000005 seconds (7 allocations: 320 bytes)

```

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 7:39am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/11 "2021-09-15T07:39:07Z")

</div>

> [@rafael.guerra](#):
>
> Thanks, `pop` seems to be the simplest by far and the whole shebang could have been written as:  
> `transformPoint(p, M) = pop(M * SA_F64[p...,1.0])`

> [@DNF](#):
>
> You can write this simpler and more general:

As far as I can tell, both of these allocate even worse than mine. My experience with Julia is that fancy short code typically allocates (at least at first) and ugly code (like my function) does not. I avoid splatting and so on at all costs.

---

<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:** [September 15, 2021, 8:24am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/12 "2021-09-15T08:24:52Z")

</div>

> [@Ribeiro](#):
>
> both of these allocate even worse than mine

No, they don’t allocate anything, the problem is your benchmarking. You cannot use `@time` for this. Use BenchmarkTools.jl.

> [@Ribeiro](#):
>
> My experience with Julia is that fancy short code typically allocates (at least at first) and ugly code (like my function) does not. I avoid splatting and so on at all costs.

No, no, no. This is way off. Write short, elegant code, and splat static arrays and tuples to your heart’s content. Just make sure that you do proper benchmarking with BenchmarkTools.

Don’t write ugly code.

```julia
jl> @btime transform(p[], M[]) setup=(p=Ref(@SVector rand(3)); M = Ref(@SMatrix rand(4,4)))
  1.500 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 8:36am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/13 "2021-09-15T08:36:01Z")

</div>

> [@DNF](#):
>
> You cannot use `@time` for this. Use BenchmarkTools.jl.

You’re right, but now I can’t reproduce my issue at all. My function is crazy slow at the moment and I have no idea why. I thought it was this part, but maybe it’s something else altogether. I benchmark it with `@btime` and see a ton of allocations, but I don’t know where they are coming from. Any ideas on troubleshooting this? I tried `@profview`, but it just showed that the code was on my main function for a long time, doing nothing (it seemed).

> [@DNF](#):
>
> Write short, elegant code

Wish I could, but typically that makes the process 50x slower, as I write nice looking code and then spend a day trying to fix allocations. I need to get smarter before I write pretty functions =.

---

<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:** [September 15, 2021, 8:38am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/14 "2021-09-15T08:38:03Z")

</div>

Which function is slow? `transformPoint` or something bigger?

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 8:41am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/15 "2021-09-15T08:41:26Z")

</div>

The bigger one, that calls `transformPoint`, but also a bunch of other stuff. It’s a big set of for loops and pretty hard to debug by parts with `@btime`.

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 8:44am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/16 "2021-09-15T08:44:33Z")

</div>

I take it back. It was easy to debug. I just commented out the lines with `transformPoint` (so the code is not doing the right thing, but it is running) and a crap ton of allocations went away. So `transformPoint` is the issue, but I don’t know why.

---

<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:** [September 15, 2021, 8:51am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/17 "2021-09-15T08:51:37Z")

</div>

Then there’s some sort of type instability probably. Can you share a bit more of the code?

Also, try `@code_warntype`

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 9:03am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/18 "2021-09-15T09:03:27Z")

</div>

That was my first instinct, but `@code_warntype` shows everything blue.

This is what the function looks like:

```julia
function myfun!(bodies,solver)
    if solver.condition
        ...
    else # this is where we are
        Threads.@threads for k in 1:M
            point₁,point₂,point₃ = ...
            for j in 1:N
                ...
                for b in 1:B
                    transformationMatrix = solver.Matrices[b];
                    point₁ = transformPoint(point₁,transformationMatrix);
					point₂ = transformPoint(point₂,transformationMatrix);
                    point₃ = transformPoint(point₃,transformationMatrix);
                    ...
                end
                ...
            end
        end
    end
    ...
    return nothing;
end

```

Unfortunately I can’t easily share something easy to reproduce.

---

<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:** [September 15, 2021, 9:12am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/19 "2021-09-15T09:12:19Z")

</div>

Check `@code_warntype` without `@threads` since `@threads` will hide its body since it gets pulled out in a closure

```julia
julia> function f()
           Threads.@threads for i in 1:5
               x = rand() > 0.5 ? 1 : "1" # type unstable
           end
       end
f (generic function with 1 method)

julia> @code_warntype f() # does not show any type instability
...

julia> function g()
           for i in 1:5
               x = rand() > 0.5 ? 1 : "1"
           end
       end
g (generic function with 1 method)

julia> @code_warntype g() # shows type unstable
Variables
  #self#::Core.Const(g)
  @_2::Union{Nothing, Tuple{Int64, Int64}}
  i::Int64
  x::Union{Int64, String}
  @_5::Union{Int64, String}

```

---

<div class="post-metadata">

**Author:** ![Ribeiro](https://avatars.discourse-cdn.com/v4/letter/r/d9b06d/32.png) [@Ribeiro](https://discourse.julialang.org/u/Ribeiro)\
**Post date:** [September 15, 2021, 10:29am UTC](https://discourse.julialang.org/t/allocation-with-staticarrays/68176/20 "2021-09-15T10:29:16Z")

</div>

Thanks a lot! This finally pointed me towards the issue, which as @DNF assumed, is a type instability problem.  
Basically, my matrix was defined as `Vector{StaticArrays.SMatrix{4,4,Float64}}`, which is not good enough, apparently. I switched to `Vector{StaticArrays.SMatrix{4,4,Float64,16}}` and it works!  
Thanks again, everyone!
