# Type instability for \`SArray\` wrapped in \`struct\`

**URL:** <https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358>\
**Category:** General Usage\
**Tags:** performance, type\
**Created:** [October 9, 2017, 5:58pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358 "2017-10-09T17:58:33Z")\
**Posts on this page:** 7\
**Page:** 1

<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:** [October 9, 2017, 5:58pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/1 "2017-10-09T17:58:33Z")

</div>

I’m struggling with an apparent type instability when wrapping a StaticArray in a `struct`. This also leads to a ~3x slowdown. Here’s an MWE running on version 0.6.0:

```julia
struct Foo
    x::SMatrix{4, 4, Float64}
end

function bar(f, M)
    B = M' * f.x * M
    return B
end
function baz(x, M)
    B = M' * x * M
    return B
end

S = @SMatrix rand(4, 4)
f = Foo(@SMatrix rand(4, 4))
x = f.x

```

Timings:

```julia
jl-0.6> @btime bar($f, $S);
  140.712 ns (4 allocations: 576 bytes)

jl-0.6> @btime baz($x, $S);
  47.050 ns (0 allocations: 0 bytes)

```

The output from `@code_warntype` is very long, so I just include some snippets:

```julia
jl-0.6> @code_warntype bar(f, S)
Variables:
  #self#::#bar
  f::Foo
  M::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  B::Any
  #temp#::StaticArrays.SArray{Tuple{4,4},Float64,2,16}

Body:
  begin
      $(Expr(:inbounds, false))
      [snip]
      # meta: location operators.jl * 424
      SSAValue(0) = ((StaticArrays._A_mul_B)($(QuoteNode(Size(4, 4))), $(QuoteNode(Size(4, 4))), #temp#::StaticArrays.SArray{Tuple{4,4},Float64,2,16}, (Core.getfield)(f::Foo, :x)::SMatrix{4,4,Float64})::Any * M::StaticArrays.SArray{Tuple{4,4},Float64,2,16})::Any
      # meta: pop location
      $(Expr(:inbounds, :pop)) # line 3:
      return SSAValue(0)
  end::Any

```

Note that `B` is inferred as `Any`, and the return type is also `Any`.

```julia
jl-0.6> @code_warntype baz(x, S)
Variables:
  #self#::#baz
  x::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  M::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  B::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  #temp#@_5::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  T@_6::Any
  #temp#@_7::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  T@_8::Any
  #temp#@_9::StaticArrays.SArray{Tuple{4,4},Float64,2,16}

Body:
  begin
      $(Expr(:inbounds, false))
      [snip]
      $(Expr(:inbounds, :pop)) # line 3:
      return #temp#@_9::StaticArrays.SArray{Tuple{4,4},Float64,2,16}
  end::StaticArrays.SArray{Tuple{4,4},Float64,2,16}

```

`B` is correctly inferred, as is the return type, though there are a couple of temps that are `Any`.

What’s going on here?

---

<div class="post-metadata">

**Author:** ![Keno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keno/32/285_2.png) [@Keno](https://discourse.julialang.org/u/Keno)\
**Post date:** [October 9, 2017, 6:04pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/2 "2017-10-09T18:04:29Z")

</div>

The type has an extra parameter for the total storage. Though planned as a future feature, right now julia can’t compute that on the fly, so you’ll have to pass it explicitly:

```julia
struct Foo
    x::SMatrix{4, 4, Float64, 4*4}
end

```

---

<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:** [October 9, 2017, 6:09pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/3 "2017-10-09T18:09:31Z")

</div>

Oh, that’s great! I was aware of that parameter, but I had the impression that is was not needed. I’m pretty sure I’ve never used it before. Is it only needed field types, not for dispatch?

---

<div class="post-metadata">

**Author:** ![Keno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keno/32/285_2.png) [@Keno](https://discourse.julialang.org/u/Keno)\
**Post date:** [October 9, 2017, 6:10pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/4 "2017-10-09T18:10:48Z")

</div>

Yes, dispatch is separate from specialization and the compiler will specialize on the subtype that has the variable set when the function called.

---

<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:** [October 9, 2017, 6:16pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/5 "2017-10-09T18:16:08Z")

</div>

A follow-up question. How do I do this for arbitrary dimensions?

```julia
struct Foo{M, N}
    x::SMatrix{M, N, Float64, M*N}
end

```

doesn’t work.

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [October 9, 2017, 6:26pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/6 "2017-10-09T18:26:54Z")

</div>

```julia
struct Foo{M, N, L}
  x::SMatrix{M, N, Float64, L}
end

```

---

<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:** [October 9, 2017, 6:27pm UTC](https://discourse.julialang.org/t/type-instability-for-sarray-wrapped-in-struct/6358/7 "2017-10-09T18:27:52Z")

</div>

You can also use [GitHub - vtjnash/ComputedFieldTypes.jl: Build types in Julia where some fields have computed types](https://github.com/vtjnash/ComputedFieldTypes.jl) to compute `L` automatically
