-
Notifications
You must be signed in to change notification settings - Fork 256
Fix type instabilities in AVL, RB and splay tree #766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Improves benchmark results for JuliaCollections#762 v0.18.10 100000 elements DataStructures.AVLTree 6.061 s (7102520 allocations: 114.48 MiB) 1000 elements DataStructures.AVLTree 36.800 ms (28637 allocations: 509.97 KiB) 10 elements DataStructures.AVLTree 134.361 μs (102 allocations: 2.23 KiB) v0.19.0-DEV 100000 elements DataStructures.AVLTree 6.113 s (7102520 allocations: 114.48 MiB) 1000 elements DataStructures.AVLTree 36.298 ms (28637 allocations: 509.97 KiB) 10 elements DataStructures.AVLTree 130.629 μs (102 allocations: 2.23 KiB) Now: 100000 elements DataStructures.AVLTree 213.450 ms (200002 allocations: 9.16 MiB) 1000 elements DataStructures.AVLTree 1.408 ms (2002 allocations: 93.80 KiB) 10 elements DataStructures.AVLTree 7.814 μs (22 allocations: 1008 bytes)
Improves benchmark results for JuliaCollections#762 Before: 100000 elements DataStructures.AVLTree 201.994 ms (200002 allocations: 9.16 MiB) DataStructures.RBTree 514.536 ms (200003 allocations: 12.21 MiB) 1000 elements DataStructures.AVLTree 1.303 ms (2002 allocations: 93.80 KiB) DataStructures.RBTree 4.395 ms (2003 allocations: 125.11 KiB) 10 elements DataStructures.AVLTree 6.998 μs (22 allocations: 1008 bytes) DataStructures.RBTree 37.789 μs (23 allocations: 1.36 KiB) Now: 100000 elements DataStructures.AVLTree 261.295 ms (204574 allocations: 9.23 MiB) DataStructures.RBTree 394.023 ms (200003 allocations: 12.21 MiB) 1000 elements DataStructures.AVLTree 1.771 ms (2014 allocations: 93.98 KiB) DataStructures.RBTree 3.190 ms (2003 allocations: 125.11 KiB) 10 elements DataStructures.AVLTree 9.797 μs (22 allocations: 1008 bytes) DataStructures.RBTree 17.728 μs (23 allocations: 1.36 KiB)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work.
Those are quite the performance improvements.
need to address the type-piracy though
We should also delete/change
https://github.com/JuliaCollections/DataStructures.jl/pull/766/files?diff=split&w=1#diff-bed9f1a3faabfaae84a4ed46f9cd059405077f120c7737ab8e782d84a54c7d32R15
and
https://github.com/JuliaCollections/DataStructures.jl/pull/766/files?diff=split&w=1#diff-11e9fe382dc297594ea9e1ef03a4076696e21896a49b4be935cd710bfa23fa37R18
which define:
RBTreeNode(d) = RBTreeNode{Any}(d)
should really be: RBTreeNode(d::K) where K = RBTreeNode{K}(d)
and similar
After some more experimenting with type specific
Specializing like
I see
Do you still suspect type piracy with the above change? Edit: Tried to discuss the problem on Discourse recently: https://discourse.julialang.org/t/dynamic-dispatch-with-union-nothing/70174/8 |
Sorry I can't estimate the impact of these changes. You should be able to edit this patch at will? |
A follow up can be made |
There is no longer any type-piracy in the code, and it is much cleaner. |
Base.setproperty!(x::AVLTreeNode{T}, f::Symbol, v) where {T} = | ||
setfield!(x, f, v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am surprised this is needed.
What happens if we delete this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #766 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically: Juno profiler shows dynamic dispatch in
setproperty!(x, f::Symbol, v) = setfield!(x, f, convert(fieldtype(typeof(x), f), v))
called by
z.rightChild = α
in left_rotate
and
z.leftChild = α
in right_rotate
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative fix seems to be
if α === nothing
z.rightChild = nothing
else
z.rightChild = α
end
but I do not feel something like this should be necessary?
Base.setproperty!(x::SplayTreeNode{K}, f::Symbol, v) where {K} = | ||
setfield!(x, f, v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar I am surprised this is needed, what happens if we delete this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #766 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here the analysis with Juno profiler is not that clear cut. It surprisingly indicates alloctions in
setproperty!(x, f::Symbol, v) = setfield!(x, f, convert(fieldtype(typeof(x), f), v))
called from
node_x.rightChild = node_y.leftChild
in left_rotate!
and
node_x.leftChild = node_y.rightChild
in right_rotate!
.
@oxinabox, @eulerkochy: any ideas how to proceed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets merge this now, it can always be improved later.
Improves benchmark results for
#762
v0.18.10
100000 elements
DataStructures.AVLTree 6.061 s (7102520 allocations: 114.48 MiB)
1000 elements
DataStructures.AVLTree 36.800 ms (28637 allocations: 509.97 KiB)
10 elements
DataStructures.AVLTree 134.361 μs (102 allocations: 2.23 KiB)
v0.19.0-DEV
100000 elements
DataStructures.AVLTree 6.113 s (7102520 allocations: 114.48 MiB)
1000 elements
DataStructures.AVLTree 36.298 ms (28637 allocations: 509.97 KiB)
10 elements
DataStructures.AVLTree 130.629 μs (102 allocations: 2.23 KiB)
Now:
100000 elements
DataStructures.AVLTree 213.450 ms (200002 allocations: 9.16 MiB)
1000 elements
DataStructures.AVLTree 1.408 ms (2002 allocations: 93.80 KiB)
10 elements
DataStructures.AVLTree 7.814 μs (22 allocations: 1008 bytes)