Can you elaborate on the reasons for your decision to do
struct FixedSizeArray{T,N,Mem<:DenseVector{T}} <: DenseArray{T,N}
mem::Mem
size::NTuple{N,Int}
end
as opposed to
mutable struct AlternativeFixedSizeArray{T,N,Mem<:DenseVector{T}} <: DenseArray{T,N}
const mem::Mem
const size::NTuple{N,Int}
end
Both inform the compiler that the fields are constant (which allows the all-important LICM). The main difference is that the wrapper AlternativeFixedSizeArray
is always heap-allocated (and it has an identity), while FixedSizeArray
tries to be stack/register allocated.
Stack/register allocation is of course nice if you have many short-lived FixedSizeArrays that are backed by longer-living Memory instances. But I don’t see this happening in real life.
Since Memory is already heap-allocated, and since most uses will presumably have the same lifetime as the backing Memory instance, you don’t save a lot of allocs/memory. But you potentially lose a lot of perf – stuff needs to always be spilled to the stack, possible boxing-unboxing conversions, etc.
PS. The trade-offs are very different for e.g. array views! These are typically short-lived, and re-use longer lived backing / parent memory instances. So views must be struct
instead of mutable struct
.