# Strange allocation

I’m writing a type to represent an affine transformation (y=Ax+b), using static arrays. Here’s the code

``````using BenchmarkTools
using StaticArrays

struct Affine{F, T, R}
matrix :: SMatrix{T, F, R}
vector :: SVector{T, R}
end

function mkaffine(::Val{T}) where T
mx = zero(SMatrix{T,T,Int})
vec = zero(SVector{T,Int})
Affine(mx, vec)    # option 1
# (mx, vec)          # option 2
end

function test()
@btime mkaffine(Val(3))
end

test()
``````

The `mkaffine()` function has been simplified from my actual use case. The `Affine` constructor is type stable, the struct has no fields with non-concrete types, everything involved is immutable and should be able to live fully on the stack. Yet I get allocations. Why?

If you comment out `Affine(mx, vec)` and return just `(mx, vec)` instead, the allocations go away. The two types should have exactly the same memory layout though.

Variant one:

``````Body::Affine{3,3,Int64}
1 ─ %1 = %new(Affine{3,3,Int64}, \$(QuoteNode([0 0 0; 0 0 0; 0 0 0])), \$(QuoteNode([0, 0, 0])))::Affine{3,3,Int64}
└──      return %1
``````

Variant 2:

``````Body::Tuple{SArray{Tuple{3,3},Int64,2,9},SArray{Tuple{3},Int64,1,3}}
1 ─     return ([0 0 0; 0 0 0; 0 0 0], [0, 0, 0])
``````

You need to specify all parameters to `SMatrix`.

Note 4 parameters.

For example:

``````julia> aff = mkaffine(Val(3));

julia> Ts = fieldtypes(typeof(aff))
(SArray{Tuple{3,3},Int64,2,L} where L, SArray{Tuple{3},Int64,1,3})

julia> isconcretetype.(Ts)
(false, true)
``````

The `L` is not specified.

1 Like

Of course, thank you. Would love it if basic arithmetic was possible with type variables so that we wouldn’t have to drag the length around.