-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Implement bounded iterators for BTree #20082
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
@@ -1376,7 +1381,7 @@ struct AbsTraversal<Impl> { | |||
|
|||
/// A single atomic step in a traversal. Either an element is visited, or an edge is followed | |||
pub enum TraversalItem<K, V, E> { | |||
Elem(K, V), | |||
Elem((K, 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.
Just for convenient interop with iterators?
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.
For the obscure opt.map(Elem)
. Ah, I should add a comment there.
Can I see tests that look like the iter tests, but bounded? Just make sure they iterate over the same number of elements. I suspect it'd be an interesting comparison. Specifically, I'm looking to see what the cost of creating the iterator looks like. |
} | ||
|
||
/// An endpoint of a range of keys. | ||
pub enum Bound<T> { |
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 feel like this shouldn't live in this file. Maybe it should go in libcore? I don't know. It just doesn't seem specific to BTrees.
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.
Agreed. I recommend moving it to the root of libcollections (and std::collections as a re-export).
Quick skim: interesting approach! Excited to dig into this. Sad to see macros. :( Will review monday if no one else does first. |
Haha "sad to see macros" is pretty much exactly what I thought when scrolling through this. |
Should we provide
Can you think of some other approach? Unfortunately, the code is quadrupled for both ends and mut/immutable. Macros deal with the latter duplication. |
b3496c9
to
d199ddb
Compare
I was assuming you were going to replace the Two RingBufs with two Vecs, which should better optimize for the "average" case. In fact you've kind've done that. Two stacks and a deque are famously "equivalent", although normally I see that used to implement a deque using two stacks, not the other way around :P The code complexity benefits probably make it worth it, though. |
Push(item) => { self.left.push_back(item); }, | ||
Pop => { self.left.pop_back(); }, | ||
Push(item) => { self.traversals.push_back(item); }, | ||
Pop => { self.traversals.pop_back(); }, | ||
} |
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.
;_; so elegant
4402b6a
to
d4e6d3d
Compare
self.head_is_edge = true; | ||
self.inner.next_kv().map(Elem) | ||
}) | ||
} |
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.
Smooth. 💖
Just need to fully parse the macro madness... |
loop { | ||
let slice = lca.slice_from(min_key).slice_to(max_key); | ||
match slice.edges { | ||
[ref $($m)* edge] => lca = edge.$as_slices_internal(), |
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.
Trying to understand this: basically you make a subslice, and if it contains a single edge you conclude that you must descend deeper? Otherwise (including the case where it's empty?), this must be the LCA?
As always: would love some more docs as to what's going on here.
7168297
to
31531c6
Compare
@gankro, done. The comment "for ranges such as..." is irrelevant for the main example. |
31531c6
to
1f62517
Compare
// lca represents the Lowest Common Ancestor, above which we never | ||
// walk, since everything else is outside the range to iterate. | ||
// ___________________ | ||
// |__0_|_80_|_85_|_90_| (root) |
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 suppose you wouldn't like to have that irrelevant part. Removed.
Needs another rebase :( |
c91326e
to
3ee4dc0
Compare
@gankro Tested, rebased (in this order 😅 ) |
@pczarn needs some changes for old_impl_check stuff, I guess? |
3ee4dc0
to
fe6cca3
Compare
Updated for old_impl_check |
Seems this didn't satisfy all the impl check issues. |
fe6cca3
to
cf2a2ab
Compare
Simplify BTree's iterators, too.
cf2a2ab
to
429c23d
Compare
@gankro Updated |
@bors r+ 429c |
Actually this is some pretty hairy stuff. @bors p=0 ? |
Aha. @bors rollup- |
Part of collections reform v1, #18424 Also, iteration is simplified: ``` before test btree::map::bench::iter_1000 ... bench: 17177 ns/iter (+/- 6302) test btree::map::bench::iter_100000 ... bench: 1735731 ns/iter (+/- 23908) test btree::map::bench::iter_20 ... bench: 386 ns/iter (+/- 148) after test btree::map::bench::iter_1000 ... bench: 15777 ns/iter (+/- 346) test btree::map::bench::iter_100000 ... bench: 1602604 ns/iter (+/- 73629) test btree::map::bench::iter_20 ... bench: 339 ns/iter (+/- 91) ``` cc @gereeter @cgaebel r? @gankro
Part of collections reform v1, #18424
Also, iteration is simplified:
cc @gereeter @cgaebel
r? @gankro