-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Implement bounded iterators for BTree #20082
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