Skip to content

Commit

Permalink
Make map() and broadcast() faster for Union{T, Missing/Nothing} eltyp…
Browse files Browse the repository at this point in the history
…es (#25828)

Storing typeof(el)/eltype(B) in a variable in the hot part of the loop kills
performance because despite being inferred as equal to Union{Type{T}, Type{Missing/Nothing}},
it is marked as ::Any. Only using typeof()/eltype() when isa() fails works around the problem
and makes map/broadcast(x->x, ::Vector{Union{Int, Missing}}) about 10 times faster.
  • Loading branch information
nalimilan authored and JeffBezanson committed Feb 6, 2018
1 parent 8076a1b commit 2d39767
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 6 deletions.
5 changes: 2 additions & 3 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -573,12 +573,11 @@ function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T
i = offs
while !done(itr, st)
el, st = next(itr, st)
S = typeof(el)
if S === T || S <: T
if el isa T || typeof(el) === T
@inbounds dest[i] = el::T
i += 1
else
R = promote_typejoin(T, S)
R = promote_typejoin(T, typeof(el))
new = similar(dest, R)
copyto!(new,1, dest,1, i-1)
@inbounds new[i] = el
Expand Down
5 changes: 2 additions & 3 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -500,14 +500,13 @@ end
@nexprs $nargs i->(@inbounds val_i = _broadcast_getindex(A_i, I_i))
# call the function
V = @ncall $nargs f val
S = typeof(V)
# store the result
if S <: eltype(B)
if V isa eltype(B)
@inbounds B[I] = V
else
# This element type doesn't fit in B. Allocate a new B with wider eltype,
# copy over old values, and continue
newB = Base.similar(B, promote_typejoin(eltype(B), S))
newB = Base.similar(B, promote_typejoin(eltype(B), typeof(V)))
for II in Iterators.take(iter, count)
newB[II] = B[II]
end
Expand Down

0 comments on commit 2d39767

Please sign in to comment.