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.

1 Like

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.

1 Like