Skip to content

Commit f2a1573

Browse files
authored
Merge pull request #123 from willtebbutt/wct/columns-perf
Fix performance problem for `Tables.Columns(::KeyedArray)`
2 parents 71f3eac + 0d36405 commit f2a1573

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "AxisKeys"
22
uuid = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5"
33
license = "MIT"
4-
version = "0.2.5"
4+
version = "0.2.6"
55

66
[deps]
77
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

src/tables.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,24 @@ Tables.columnaccess(::Type{<:KeyedArray{T,N,AT}}) where {T,N,AT} =
3737
function Tables.columns(A::Union{KeyedArray, NdaKa})
3838
L = hasnames(A) ? (dimnames(A)..., :value) :
3939
(ntuple(d -> Symbol(:dim_,d), ndims(A))..., :value)
40-
R = keys_or_axes(A)
41-
G = ntuple(ndims(A)) do d
42-
vec([rs[d] for rs in Iterators.product(R...)])
43-
# _vec(rs[d] for rs in Iterators.product(R...))
44-
end
40+
G = _get_keys_columns(keys_or_axes(A))
4541
C = (G..., vec(parent(A)))
4642
NamedTuple{L}(C)
4743
end
4844

45+
# indices is a tuple, the dth element of which is an index for the dth column of R.
46+
# By using these indices, and mapping over the columns of R, the compiler seems to
47+
# successfully infer the types in G, because it knows the element types of each column
48+
# of R, so is presumably able to unroll the call to map.
49+
# The previous implementation called `Iterators.product` on `R` and pulled out
50+
# the dth element of `indices`, whose type it could not infer.
51+
function _get_keys_columns(R)
52+
R_inds = map(eachindex, R)
53+
return map(R, ntuple(identity, length(R))) do r, d
54+
vec([r[indices[d]] for indices in Iterators.product(R_inds...)])
55+
end
56+
end
57+
4958
function Tables.Schema(nt::NamedTuple) # 🏴‍☠️
5059
L = keys(nt)
5160
T = map(v -> typeof(first(v)), values(nt))

test/_packages.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ end
4949
@test keys(first(Tables.rows(N))) == (:a, :b, :value)
5050

5151
@test Tables.columns(N).a == [11, 12, 11, 12, 11, 12]
52+
53+
# Regression test: https://github.com/mcabbott/AxisKeys.jl/pull/123
54+
@testset "Tables.columns(::AxisKeys) type stability" begin
55+
a = randn(5)
56+
b = randn(Float32, 4)
57+
@inferred AxisKeys._get_keys_columns((a, b))
58+
X = wrapdims(randn(5, 4); a, b)
59+
@inferred Tables.columns(X)
60+
end
5261
end
5362
@testset "sink" begin
5463
A = KeyedArray(rand(24, 11, 3); time = 0:23, loc = -5:5, id = ["a", "b", "c"])

0 commit comments

Comments
 (0)