-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Max & Min on BTreeMap are unexpectedly slow #59947
Comments
Correct me if I'm wrong, but it seems like This should be done for Given that |
|
I think there's another possible issue with this change. Currently, Do we have a policy on when specializing an iterator method is appropriate? My concern is that if we optimize some special cases, then users might expect other similar cases to be optimized in the same way, leading to confusion when that doesn't happen. I wonder what we can do to prevent such issues from popping up here. |
There are other optimizations that will let you run off a performance cliff if you deviate from the happy path. E.g. vec allocation relies on the OS giving you zeroed pages to avoid initializing it, making even very large empty vecs fairly cheap. If you allocate a vec but pre-init to some other value it can suddenly get a lot slower. Leaving performance on the table to reduce surprises does not seem like a great tradeoff. And add ing |
I think the only observable change would be if the key type has side effects in |
let mut it = my_map.into_iter();
it.by_ref().min();
println!("{:?}", it.next());
EDIT: never mind I'm dumb |
Calling |
I recall a conversation about why we don't make |
…Simulacrum Shortcuts for min/max on double-ended BTreeMap/BTreeSet iterators Closes rust-lang#59947: a performance tweak that might benefit some. Optimizes `min` and `max ` on all btree double-ended iterators that do not drop, i.e. the iterators created by: - `BTreeMap::iter` - `BTreeMap::iter_mut` - `BTreeMap::keys` and `BTreeSet::iter` - `BTreeMap::range` and `BTreeSet::range` - `BTreeMap::range_mut` Also in these (currently) single-ended iterators, but obviously for `min` only: - `BTreeSet::difference` - `BTreeSet::intersection` - `BTreeSet::symmetric_difference` - `BTreeSet::union` Did not do this in iterators created by `into_iter` to preserve drop order, as outlined in rust-lang#62316. Did not do this in iterators created by `drain_filter`, possibly to preserve drop order, possibly to preserve predicate invocation, mostly to not have to think about it too hard (I guess maybe it wouldn't be a change for `min`, which is the only shortcut possible in this single-ended iterator).
…Simulacrum Shortcuts for min/max on double-ended BTreeMap/BTreeSet iterators Closes rust-lang#59947: a performance tweak that might benefit some. Optimizes `min` and `max ` on all btree double-ended iterators that do not drop, i.e. the iterators created by: - `BTreeMap::iter` - `BTreeMap::iter_mut` - `BTreeMap::keys` and `BTreeSet::iter` - `BTreeMap::range` and `BTreeSet::range` - `BTreeMap::range_mut` Also in these (currently) single-ended iterators, but obviously for `min` only: - `BTreeSet::difference` - `BTreeSet::intersection` - `BTreeSet::symmetric_difference` - `BTreeSet::union` Did not do this in iterators created by `into_iter` to preserve drop order, as outlined in rust-lang#62316. Did not do this in iterators created by `drain_filter`, possibly to preserve drop order, possibly to preserve predicate invocation, mostly to not have to think about it too hard (I guess maybe it wouldn't be a change for `min`, which is the only shortcut possible in this single-ended iterator).
…Simulacrum Shortcuts for min/max on double-ended BTreeMap/BTreeSet iterators Closes rust-lang#59947: a performance tweak that might benefit some. Optimizes `min` and `max ` on all btree double-ended iterators that do not drop, i.e. the iterators created by: - `BTreeMap::iter` - `BTreeMap::iter_mut` - `BTreeMap::keys` and `BTreeSet::iter` - `BTreeMap::range` and `BTreeSet::range` - `BTreeMap::range_mut` Also in these (currently) single-ended iterators, but obviously for `min` only: - `BTreeSet::difference` - `BTreeSet::intersection` - `BTreeSet::symmetric_difference` - `BTreeSet::union` Did not do this in iterators created by `into_iter` to preserve drop order, as outlined in rust-lang#62316. Did not do this in iterators created by `drain_filter`, possibly to preserve drop order, possibly to preserve predicate invocation, mostly to not have to think about it too hard (I guess maybe it wouldn't be a change for `min`, which is the only shortcut possible in this single-ended iterator).
Hello,
The use of iterator's
max
andmin
function do not seams to take advantage of the specific ordering of BTreeMap and looks like it is browsing the whole container.Although it is still possible to have fast access to minimum and maximum element by using
first
andfirst_back
, this is not semantically explicite and you can expect that developers may not know the subtilities regarding BTreeMap's implementation and could assume the complexity should be the same.Here is the benchmark result
and here is the benchmark code:
I don't know the details of the trait implementation, but I think it would be very nice for the community if you can make
std::collections::btree_map::Iter
take advantage of the ordering. :)The text was updated successfully, but these errors were encountered: