Skip to content

Commit b562bec

Browse files
author
Pietro Vertechi
authored
add optimized append (#111)
* add optimized append * only do optimization on julia 1.3 * add tests
1 parent 5099132 commit b562bec

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

src/collect.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ _collect_structarray!(dest, itr, st, ::Nothing) =
6464

6565
function collect_to_structarray!(dest::AbstractArray, itr, offs, st)
6666
# collect to dest array, checking the type of each result. if a result does not
67-
# match, widen the result type and re-dispatch.
67+
# match, widen_from_instance the result type and re-dispatch.
6868
i = offs
6969
while true
7070
elem = iterate(itr, st)
@@ -74,7 +74,7 @@ function collect_to_structarray!(dest::AbstractArray, itr, offs, st)
7474
@inbounds dest[i] = el
7575
i += 1
7676
else
77-
new = widen(dest, i, el)
77+
new = widen_from_instance(dest, i, el)
7878
@inbounds new[i] = el
7979
return collect_to_structarray!(new, itr, i+1, st)
8080
end
@@ -84,7 +84,7 @@ end
8484

8585
function grow_to_structarray!(dest::AbstractArray, itr, elem = iterate(itr))
8686
# collect to dest array, checking the type of each result. if a result does not
87-
# match, widen the result type and re-dispatch.
87+
# match, widen_from_instance the result type and re-dispatch.
8888
i = length(dest)+1
8989
while elem !== nothing
9090
el, st = elem
@@ -93,7 +93,7 @@ function grow_to_structarray!(dest::AbstractArray, itr, elem = iterate(itr))
9393
elem = iterate(itr, st)
9494
i += 1
9595
else
96-
new = widen(dest, i, el)
96+
new = widen_from_instance(dest, i, el)
9797
push!(new, el)
9898
return grow_to_structarray!(new, itr, iterate(itr, st))
9999
end
@@ -102,7 +102,12 @@ function grow_to_structarray!(dest::AbstractArray, itr, elem = iterate(itr))
102102
end
103103

104104
# Widen `dest` to contain `el` and copy until index `i-1`
105-
widen(dest::AbstractArray{S}, i, el::T) where {S, T} = _widenstructarray(dest, i, _promote_typejoin(S, T))
105+
widen_from_instance(dest::AbstractArray, i, el::T) where {T} = widen_from_type(dest, i, T)
106+
# Widen `dest` to contain elements of type `T` and copy until index `i-1`
107+
function widen_from_type(dest::AbstractArray{S}, i, ::Type{T}) where {S, T}
108+
U = _promote_typejoin(S, T)
109+
return _widenstructarray(dest, i, U)
110+
end
106111

107112
function _widenstructarray(dest::StructArray, i, ::Type{T}) where {T}
108113
sch = hasfields(T) ? staticschema(T) : nothing
@@ -145,11 +150,20 @@ function _append!!(dest::AbstractVector, itr, ::Union{Base.HasShape, Base.HasLen
145150
fr === nothing && return dest
146151
el, st = fr
147152
i = lastindex(dest) + 1
148-
new = iscompatible(el, dest) ? dest : widen(dest, i, el)
153+
new = iscompatible(el, dest) ? dest : widen_from_instance(dest, i, el)
149154
resize!(new, length(dest) + n)
150155
@inbounds new[i] = el
151156
return collect_to_structarray!(new, itr, i + 1, st)
152157
end
153158

154159
_append!!(dest::AbstractVector, itr, ::Base.SizeUnknown) =
155160
grow_to_structarray!(dest, itr)
161+
162+
# Optimized version when element collection is an `AbstractVector`
163+
# This only works for julia 1.3 or greater, which has `append!` for `AbstractVector`
164+
@static if VERSION v"1.3.0"
165+
function append!!(dest::V, v::AbstractVector{T}) where {V<:AbstractVector, T}
166+
new = iscompatible(T, V) ? dest : widen_from_type(dest, length(dest) + 1, T)
167+
return append!(new, v)
168+
end
169+
end

src/structarray.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ Base.@propagate_inbounds function Base.setindex!(s::StructArray{<:Any, <:Any, <:
169169
s
170170
end
171171

172-
function Base.push!(s::StructArray, vals)
172+
function Base.push!(s::StructVector, vals)
173173
foreachfield(push!, s, vals)
174174
return s
175175
end
176176

177-
function Base.append!(s::StructArray, vals)
177+
function Base.append!(s::StructVector, vals::StructVector)
178178
foreachfield(append!, s, vals)
179179
return s
180180
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ end
681681
itr = [(a = 1, b = 2), (a = 1, b = 2), (a = 1, b = 12)]
682682
itr_examples = [
683683
("HasLength", () -> itr),
684+
("StructArray", () -> StructArray(itr)),
684685
("SizeUnknown", () -> (x for x in itr if isodd(x.a))),
685686
# Broken due to https://github.com/JuliaArrays/StructArrays.jl/issues/100:
686687
# ("empty", (x for x in itr if false)),

0 commit comments

Comments
 (0)