Skip to content
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

BTreeMap: remove shared root #70111

Merged
merged 7 commits into from
Mar 21, 2020
Merged

Conversation

Mark-Simulacrum
Copy link
Member

@Mark-Simulacrum Mark-Simulacrum commented Mar 18, 2020

This replaces the shared root with Options in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review.

Note that BTreeMap::new() continues to not allocate.

Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch.

 name                                 alloc-bench-a ns/iter  alloc-bench-b ns/iter  diff ns/iter  diff %  speedup
 btree::map::iter_mut_20              20                     21                                1   5.00%   x 0.95
 btree::set::clone_100                1,360                  1,439                            79   5.81%   x 0.95
 btree::set::clone_100_and_into_iter  1,319                  1,434                           115   8.72%   x 0.92
 btree::set::clone_10k                143,515                150,991                       7,476   5.21%   x 0.95
 btree::set::clone_10k_and_clear      142,792                152,916                      10,124   7.09%   x 0.93
 btree::set::clone_10k_and_into_iter  146,019                154,561                       8,542   5.85%   x 0.94

@Mark-Simulacrum
Copy link
Member Author

I was unable to run miri as it's currently unavailable in nightly, but we can hold off landing this until miri returns (or fix potential fallout once it returns). Tests do pass locally, including under valgrind.

@rust-highfive

This comment has been minimized.

@Mark-Simulacrum
Copy link
Member Author

Looks like the gdb pretty printing broke as a result of this; I am completely unfamiliar with that side of things but will try to investigate and fix.

@Mark-Simulacrum
Copy link
Member Author

Let's r? @cuviper here as they've recently also taken a look at this code, though I would personally feel comfortable with @ssomers reviewing as well.

@rust-highfive

This comment has been minimized.

@Mark-Simulacrum
Copy link
Member Author

Hm, tests did pass locally so I'm guessing this is a gdb-version specific issue? It looks like perhaps the way enums are decoded differs though. Or, as another alternative I guess, we have some layout optimization applying in stage 2 which is absent in stage 1 (where I tested).

Part of me wants to just comment out the Btree debug pretty printing entirely...

Copy link
Contributor

@ssomers ssomers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how you came up with that gdb code, but I sure don't know how to unwrap an option there. You are aware it's being changed in #60826?

src/liballoc/collections/btree/map.rs Outdated Show resolved Hide resolved
Comment on lines +449 to 451
front: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
back: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea that popped up: did you consider making some static handle that could be used here, to avoid the Option(s) and the code around them? Since in that case front==back so the handles would never be dereferenced.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I did consider this. I suspect we'd run into many of the same problems as we did with the shared root (or end up having to write a bunch of boilerplate code) -- I would prefer to avoid that. There is at least once niche in the NodeRef (and Handle doesn't use it up) so I think this is essentially zero-cost anyway.

src/liballoc/collections/btree/node.rs Show resolved Hide resolved
Copy link
Member

@cuviper cuviper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In node.rs, it looks like a really nice cleanup! In map.rs, the extra unwraps and such are a little annoying, but not too bad. Overall, it looks like an improvement in safety though.

src/liballoc/collections/btree/node.rs Show resolved Hide resolved
src/liballoc/collections/btree/map.rs Outdated Show resolved Hide resolved
src/liballoc/collections/btree/map.rs Show resolved Hide resolved
@Mark-Simulacrum
Copy link
Member Author

I was aware of #60826, but had forgotten about it :)

It looks like that doesn't actually change the BTree printing at all pretty much so this PR would need to fix it up if we want it to work. I'm not actually personally sure how useful it is for it to work :)

Maybe @ortem has some advice on how best to work around the introduction of the Option here -- clearly my haphazard "this seems to get us what we want" is not passing CI, at least. I've pushed up a commit to attempt to debug the Some trouble now.

@rust-highfive

This comment has been minimized.

@ssomers
Copy link
Contributor

ssomers commented Mar 19, 2020

If it's any comfort, your latest commit tests fine on my linux box (with gdb 8.2.1 as opposed to 8.1.0 on rust-highfive).

@Mark-Simulacrum
Copy link
Member Author

Yeah, every commit since I tried to fix it has tested fine with my local GDB (8.3.1) too. If this doesn't work I'll try to get a 8.1 gdb copy locally I guess...

@rust-highfive

This comment has been minimized.

@Mark-Simulacrum
Copy link
Member Author

@cuviper -- looks like gdb pretty printing is working now, I believe this is ready for another review pass.

@Mark-Simulacrum Mark-Simulacrum added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 19, 2020
@cuviper
Copy link
Member

cuviper commented Mar 19, 2020

LGTM!

@bors r+

@bors
Copy link
Contributor

bors commented Mar 19, 2020

📌 Commit db7a697 has been approved by cuviper

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 19, 2020
@ssomers
Copy link
Contributor

ssomers commented Mar 19, 2020

You could also remove test case test_into_key_slice_with_shared_root_past_bounds and there's another outdated "shared root" comment in that file.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 19, 2020
…cuviper

BTreeMap: remove shared root

This replaces the shared root with `Option`s in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review.

Note that `BTreeMap::new()` continues to not allocate.

Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch.

```
 name                                 alloc-bench-a ns/iter  alloc-bench-b ns/iter  diff ns/iter  diff %  speedup
 btree::map::iter_mut_20              20                     21                                1   5.00%   x 0.95
 btree::set::clone_100                1,360                  1,439                            79   5.81%   x 0.95
 btree::set::clone_100_and_into_iter  1,319                  1,434                           115   8.72%   x 0.92
 btree::set::clone_10k                143,515                150,991                       7,476   5.21%   x 0.95
 btree::set::clone_10k_and_clear      142,792                152,916                      10,124   7.09%   x 0.93
 btree::set::clone_10k_and_into_iter  146,019                154,561                       8,542   5.85%   x 0.94
```
@JohnTitor
Copy link
Member

Failed in #70169 (comment)
@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 20, 2020
This simplifies the node manipulation, as we can (in later commits) always know
when traversing nodes that we are not in a shared root.
We no longer have a separate header because the shared root is gone; all code
can work solely with leafs now.
This makes ensure_root_is_owned return a reference to the (now guaranteed to
exist) root, allowing callers to operate on it without going through another
unwrap.

Unfortunately this is only rarely useful as it's frequently the case that both
the length and the root need to be accessed and field-level borrows in methods
don't yet exist.
@Mark-Simulacrum
Copy link
Member Author

@bors r=cuviper Fixed up the pretty printing code (at least the test-various builder is passing locally now, and gdb 8.3 with the debugger script in this PR also does the right thing).

@bors
Copy link
Contributor

bors commented Mar 20, 2020

📌 Commit bce7f6f has been approved by cuviper

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 20, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 21, 2020
…cuviper

BTreeMap: remove shared root

This replaces the shared root with `Option`s in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review.

Note that `BTreeMap::new()` continues to not allocate.

Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch.

```
 name                                 alloc-bench-a ns/iter  alloc-bench-b ns/iter  diff ns/iter  diff %  speedup
 btree::map::iter_mut_20              20                     21                                1   5.00%   x 0.95
 btree::set::clone_100                1,360                  1,439                            79   5.81%   x 0.95
 btree::set::clone_100_and_into_iter  1,319                  1,434                           115   8.72%   x 0.92
 btree::set::clone_10k                143,515                150,991                       7,476   5.21%   x 0.95
 btree::set::clone_10k_and_clear      142,792                152,916                      10,124   7.09%   x 0.93
 btree::set::clone_10k_and_into_iter  146,019                154,561                       8,542   5.85%   x 0.94
```
Centril added a commit to Centril/rust that referenced this pull request Mar 21, 2020
…cuviper

BTreeMap: remove shared root

This replaces the shared root with `Option`s in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review.

Note that `BTreeMap::new()` continues to not allocate.

Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch.

```
 name                                 alloc-bench-a ns/iter  alloc-bench-b ns/iter  diff ns/iter  diff %  speedup
 btree::map::iter_mut_20              20                     21                                1   5.00%   x 0.95
 btree::set::clone_100                1,360                  1,439                            79   5.81%   x 0.95
 btree::set::clone_100_and_into_iter  1,319                  1,434                           115   8.72%   x 0.92
 btree::set::clone_10k                143,515                150,991                       7,476   5.21%   x 0.95
 btree::set::clone_10k_and_clear      142,792                152,916                      10,124   7.09%   x 0.93
 btree::set::clone_10k_and_into_iter  146,019                154,561                       8,542   5.85%   x 0.94
```
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 21, 2020
Rollup of 16 pull requests

Successful merges:

 - rust-lang#65097 (Make std::sync::Arc compatible with ThreadSanitizer)
 - rust-lang#69033 (Use generator resume arguments in the async/await lowering)
 - rust-lang#69997 (add `Option::{zip,zip_with}` methods under "option_zip" gate)
 - rust-lang#70038 (Remove the call that makes miri fail)
 - rust-lang#70058 (can_begin_literal_maybe_minus: `true` on `"-"? lit` NTs.)
 - rust-lang#70111 (BTreeMap: remove shared root)
 - rust-lang#70139 (add delay_span_bug to TransmuteSizeDiff, just to be sure)
 - rust-lang#70165 (Remove the erase regions MIR transform)
 - rust-lang#70166 (Derive PartialEq, Eq and Hash for RangeInclusive)
 - rust-lang#70176 (Add tests for rust-lang#58319 and rust-lang#65131)
 - rust-lang#70177 (Fix oudated comment for NamedRegionMap)
 - rust-lang#70184 (expand_include: set `.directory` to dir of included file.)
 - rust-lang#70187 (more clippy fixes)
 - rust-lang#70188 (Clean up E0439 explanation)
 - rust-lang#70189 (Abi::is_signed: assert that we are a Scalar)
 - rust-lang#70194 (#[must_use] on split_off())

Failed merges:

r? @ghost
@bors bors merged commit 9d9e381 into rust-lang:master Mar 21, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 26, 2020
…r=Mark-Simulacrum

Test and fix gdb pretty printing more

Over time I had oversimplified the test case for rust-lang#68098: it does not have an internal node to print so it does not test what it pretend to test. And then I also realized not spotting the same mistake reviewing rust-lang#70111, and more likely to occur in the wild. Now, both test cases fail if you put back the flawed python code.

r? @Mark-Simulacrum
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 27, 2020
…Mark-Simulacrum

Test and fix gdb pretty printing more

Over time I had oversimplified the test case for rust-lang#68098: it does not have an internal node to print so it did not test what it pretended to test. And then I also realized not spotting the same mistake reviewing rust-lang#70111, and more likely to occur in the wild. Now, both test cases fail if you put back the flawed python code.

r? @Mark-Simulacrum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants