Deep copy of Array in Struct in NamedTuple

I am creating and returning a NamedTuple cache

mystruct = MyStruct{Float64}(42, 42, 42)
cache = (; foo, bar, mystruct)
return cache

where mystruct is an object of the mutable struct MyStruct which contains an array

mutable struct MyStruct{uEltype <: Real}
  arr::Array{uEltype}

  function MyStruct{uEltype}(n1::Integer, n2::Integer, n3::Integer) where {uEltype <: Real}
      new(Array{uEltype}(undef, n1, n2, n3))
  end
end

When I later access cache.mystruct.arr in a different function it seems that arr is re-allocated, which I would avoid - ideally, I allocate storage once in mystruct = MyStruct{Float64}(42, 42, 42) and can access that later on.

In contrast, however, if I make arr a member of the named tuple itself, i.e.,

arr = Array{Float64}(undef, 42, 42, 42)
cache = (; foo, bar, arr)
return cache

no re-allocations are necessary when cache.arr is accessed later on.
What is going on here? Is the memory reserved by mystruct = MyStruct{Float64}(42, 42, 42) considered out of scope once this function is left?

Can you show how you determine that arr is being re-allocated upon access?

Apart from that, consider adjusting the type of the arr member of MyStruct to more specific arr::Array{uEltype, 3} (3-dimensional array). Also, if you intend to keep a single array, you don’t have to declare MyStruct as mutable: mutable allows you to set arr to a whole new array, but if you just want to change the elements of arr, you don’t need mutable.

consider adjusting the type of the arr member of MyStruct to more specific arr::Array{uEltype, 3} (3-dimensional array)

That actually did the trick (for whatever reason), thanks a lot!

I am glad it helped.

You probably observed unexpected allocations somewhere in your program. The original code was not type-stable, which is likely the reason. However, it does not mean that the whole array was re-allocated.