Skip to content

Commit

Permalink
faster replace on Dict and Set (#33739)
Browse files Browse the repository at this point in the history
This optimizes replace and replace! functions on Dict (and Set) based on the internals.
  • Loading branch information
rfourquet authored Oct 10, 2020
1 parent 7f7ab69 commit 8a52ea4
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions base/set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,46 @@ function _replace!(new::Callable, res::AbstractArray, A::AbstractArray, count::I
end
res
end

### specialization for Dict / Set

function _replace!(new::Callable, t::Dict{K,V}, A::Dict{K,V}, count::Int) where {K,V}
# we ignore A, which is supposed to be equal to the destination t,
# as it can generally be faster to just replace inline
count == 0 && return t
c = 0
news = Pair{K,V}[]
i = skip_deleted_floor!(t)
@inbounds while i != 0
k1, v1 = t.keys[i], t.vals[i]
x1 = Pair{K,V}(k1, v1)
x2 = new(x1)
if x1 !== x2
k2, v2 = first(x2), last(x2)
if isequal(k1, k2)
t.keys[i] = k2
t.vals[i] = v2
t.age += 1
else
_delete!(t, i)
push!(news, x2)
end
c += 1
c == count && break
end
i = i == typemax(Int) ? 0 : skip_deleted(t, i+1)
end
for n in news
push!(t, n)
end
t
end

function _replace!(new::Callable, t::Set{T}, ::Set{T}, count::Int) where {T}
_replace!(t.dict, t.dict, count) do kv
k = first(kv)
k2 = new(k)
k2 === k ? kv : k2 => nothing
end
t
end

0 comments on commit 8a52ea4

Please sign in to comment.