[ANN] FixedSizeArrays.jl: What Array probably should have been

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.