# Avoiding allocation when accessing fields of a StructArray inside a Struct

**URL:** <https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168>\
**Category:** Performance\
**Created:** [August 23, 2022, 2:36am UTC](https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168 "2022-08-23T02:36:27Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![cuihantao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cuihantao/32/8783_2.png) [@cuihantao](https://discourse.julialang.org/u/cuihantao)\
**Post date:** [August 23, 2022, 2:36am UTC](https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168/1 "2022-08-23T02:36:27Z")

</div>

Let me start with the MWE

```julia
using StructArrays
using BenchmarkTools

# the struct to be converted to StructArray
struct Foo1
    a::Float64
    b::Float64
end

a = [1.0, 2.0]
b = [3.0, 4.0]

foo1 = StructArray{Foo1}(a=a, b=b)

# `Bar1.foo` is type-annotated by hand
struct Bar1
    foo::StructVector{Foo1}
end

# `Bar2.foo` is type-annotated using that given by `typeof(foo1)`
struct Bar2
    foo::StructVector{Foo1, NamedTuple{(:a, :b), Tuple{Vector{Float64}, Vector{Float64}}}, Int64}
end

function access_bar(bar)
    bar.foo.a
end

@code_warntype access_bar(bar1)

#=
Output:

Body::Any
1 ─ %1 = Base.getproperty(bar, :foo)::StructVector
│ %2 = Base.getproperty(%1, :a)::Any
└── return %2
=#

@code_warntype access_bar(bar2)

#=
Body::Vector{Float64}
1 ─ %1 = Base.getproperty(bar, :foo)::StructVector{Foo1, NamedTuple{(:a, :b), Tuple{Vector{Float64}, Vector{Float64}}}, Int64}
│ %2 = Base.getproperty(%1, :a)::Vector{Float64}
└── return %2
=#

@btime access_bar(bar1)
# 52.019 ns (1 allocation: 32 bytes)

@btime access_bar(bar2)
# 13.889 ns (0 allocations: 0 bytes)

```

My question is, are there alternative solutions for getting rid of the allocation?

Annotating like `foo::StructVector{Foo1, NamedTuple{(:a, :b), Tuple{Vector{Float64}, Vector{Float64}}}, Int64}` is not so convenient as the StructArray has many fields, and I’d like the code to be generic when type changes (such as for using CuArray instead).

If annotating the type is the only solution, are there short-hand aliases for `foo::StructVector{Foo1, NamedTuple{(:a, :b), Tuple{Vector{Float64}, Vector{Float64}}}, Int64}`?

---

<div class="post-metadata">

**Author:** ![cuihantao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cuihantao/32/8783_2.png) [@cuihantao](https://discourse.julialang.org/u/cuihantao)\
**Post date:** [August 23, 2022, 3:25am UTC](https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168/2 "2022-08-23T03:25:25Z")

</div>

After some digging, I realized that `NTuple{2, Vector{Float64}}` can be used.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 23, 2022, 5:22am UTC](https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168/3 "2022-08-23T05:22:34Z")

</div>

> [@cuihantao](#):
>
> ```julia
> struct Bar1
> foo::StructVector{Foo1}
> end
> 
> ```

This is not a concrete type, so it ends up being boxed. You can get type stability with writing about this much like so:

```julia
struct MyStruct{T <: StructVector{Foo1}}
    foo::T
end

```

---

<div class="post-metadata">

**Author:** ![cuihantao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cuihantao/32/8783_2.png) [@cuihantao](https://discourse.julialang.org/u/cuihantao)\
**Post date:** [August 23, 2022, 7:42pm UTC](https://discourse.julialang.org/t/avoiding-allocation-when-accessing-fields-of-a-structarray-inside-a-struct/86168/4 "2022-08-23T19:42:17Z")

</div>

Thanks! This is the issue.
