-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Currently, a StaticStrideArray
must be a mutable struct
so that we can get reliable pointers to it's storage in order to avoid interacting with the NTuple
data.
However, this causes problems with StaticStrideArrays
if they cross non-inlined function boundaries because then the storage data will end up on the heap even if it doesn't need to be there, requiring us to deal with the scariness of PtrArrays @gc_preserve
.
One possible solution to this problem would be to have StaticStrideArray
be an immutable struct
, and then have a MutableStaticStrideArray
that can be created from it on-demand in order to get a pointer, and then converted right back to the immutable version as soon as we're done.
Here's a little demo of what I'm imagining:
using StrideArrays, StrideArraysCore
using StrideArraysCore: StaticStrideArray
macro new(T, args...)
Expr(:new, T, args...) |> esc
end
struct FrozenStaticStrideArray{T, N, R, S, X, O, L} <: AbstractStrideArray{T, N, R, S, X, O}
data::NTuple{L,T}
end
function freeze(sa::StaticStrideArray{T, N, R, S, X, O, L}) where {T, N, R, S, X, O, L}
@new FrozenStaticStrideArray{T, N, R, S, X, O, L} getfield(sa, 1)
end
function thaw(fsa::FrozenStaticStrideArray{T, N, R, S, X, O, L}) where {T, N, R, S, X, O, L}
@new StaticStrideArray{T, N, R, S, X, O, L} getfield(fsa, 1)
end
function Base.getindex(fsa::FrozenStaticStrideArray, i::Int...)
thaw(fsa)[i...]
end
let
sa = StaticStrideArray{Float64}(undef, (static(1000),)) .= 1
fsa = freeze(sa)
@btime $sa[1000]
@btime $fsa[1000]
endl
#+RESULTS:
: 1.940 ns (0 allocations: 0 bytes)
: 1.939 ns (0 allocations: 0 bytes)
I think having an immutable variant like this could make this a much more convincing replacement for StaticArrays.jl.