Alright, here is a better example. This is a pared-down version of what I’m doing in ComponentArrays.jl. I’m using @inline
for getindex
here and am still seeing the issue.
idx_ax(x) = (x, NamedTuple())
idx_ax(x::Tuple) = x
struct Axis{IdxMap} end
Axis(IdxMap) = Axis{IdxMap}()
struct ComponentArray{Axes,T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
data::A
axes::Axes
ComponentArray(data::A, ax::Ax) where {A<:AbstractArray{T,N},Ax<:Axis} where {T,N} = new{Ax,T,N,A}(data, ax)
ComponentArray(data, ax) = data
end
@inline getdata(x::ComponentArray) = getfield(x, :data)
@inline getaxes(x::ComponentArray) = getfield(x, :axes)
@inline getaxes(::Type{ComponentArray{Ax,T,N,A}}) where {Ax<:Axis,T,N,A} = Ax
Base.size(x::ComponentArray) = size(getdata(x))
@inline Base.getindex(x::ComponentArray, s::Symbol) = _getindex(x, Val(s))
@inline Base.getindex(x::ComponentArray, idx) = getdata(x)[idx]
@inline Base.getindex(::Type{Axis{IdxMap}}, s::Symbol) where IdxMap = idx_ax(getfield(IdxMap, s))
@generated function _getindex(x::ComponentArray, ::Val{s}) where s
ind_tup = getindex(getaxes(x), s)
idx = ind_tup[1]
new_ax = Axis(ind_tup[2])
return :(Base.@_inline_meta; ComponentArray(Base.maybeview(getdata(x), $idx), $new_ax))
end
@inline Base.getproperty(x::ComponentArray, s::Symbol) = _getindex(x, Val(s))
Constant propagation works just fine on getproperty
, but I can’t seem to get it to work with getindex
:
ax = Axis((a=1, b=2:4, c=(5:8, (a=1:3, b=4))))
ca = ComponentArray(rand(8), ax)
using BenchmarkTools
@btime $ca.a # 1.099 ns (0 allocations: 0 bytes)
@btime $ca[:a] # 4.314 μs (1 allocation: 16 bytes)
@btime $ca.c.b # 1.099 ns (0 allocations: 0 bytes)
@btime $ca[:c][:b] # 8.933 μs (3 allocations: 80 bytes)
@btime $ca.c.a # 13.300 ns (2 allocations: 64 bytes)
@btime $ca[:c][:a] # 8.833 μs (4 allocations: 128 bytes)
function test_prop(x)
return getproperty(x, :c)
end
function test_index(x)
return getindex(x, :c)
end
@btime test_prop($ca) # 13.400 ns (2 allocations: 64 bytes)
@btime test_index($ca) # 4.386 μs (2 allocations: 64 bytes)