Uh oh!
There was an error while loading. Please reload this page.
Specialize Iterator for &mut I where I: Sized - #82185
Conversation
rust-highfive
commented
Feb 16, 2021
(rust-highfive has picked a reviewer for you, use r? to override) |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This comment has been minimized.
This comment has been minimized.
Is the intermediate trait SpecSizedIterator a workaround? Couldn't it be specialized on the Sized bound for the plain |
the8472
commented
Feb 16, 2021
Current std policy says to use private helper traits. https://std-dev-guide.rust-lang.org/code-considerations/using-unstable-lang/specialization.html |
Mark-Simulacrum
commented
Feb 20, 2021
r? @cuviper (or someone else more familiar with iterator code) |
cuviper
commented
Feb 21, 2021
Let's check the general perf effect: @bors try @rust-timer queue |
rust-timer
commented
Feb 21, 2021
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
bors
commented
Feb 21, 2021
⌛ Trying commit a09399b1f1ba90d72fdc4eadf65d0ab459a96287 with merge 4bf6a12cc7384e44f61e55b762c4efb6612c5aca... |
bors
commented
Feb 21, 2021
☀️ Try build successful - checks-actions |
rust-timer
commented
Feb 21, 2021
Queued 4bf6a12cc7384e44f61e55b762c4efb6612c5aca with parent d2b38d6, future comparison URL. |
rust-timer
commented
Feb 21, 2021
Finished benchmarking try commit (4bf6a12cc7384e44f61e55b762c4efb6612c5aca): comparison url. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up. @bors rollup=never |
cuviper
commented
Mar 3, 2021
@SkiFire13 those perf results don't look promising -- what's your take on it? |
SkiFire13
commented
Mar 3, 2021
I'm not quite sure but my guesses are:
|
crlf0710
commented
Mar 20, 2021
@SkiFire13 Ping from triage, what's next steps here? |
SkiFire13
commented
Mar 21, 2021
After the perf run I decided to focus on solving the regressing benchmarks, hoping that their cause is the same as the regressions in the perf run. I tried inling more methods and changing |
the8472
commented
Mar 21, 2021
If you click on the percentages you'll see a breakdown by what's consuming more time. It's mostly spending more time in LLVM, so one thing you could investigate is whether these changes caused more llvm IR to be emitted for those benchmarked crates. cargo llvm-lines can be useful there. In the past optimization attempts in
Just run the experiment? Another idea would be measuring the shuffling of the default implementations into separate traits ( |
crlf0710
commented
Apr 9, 2021
@SkiFire13 Ping from triage, any updates on this? |
…old implementations for &mut impl DoubleEndedIterator
03cf754 to
17350deCompareMark-Simulacrum
commented
May 11, 2021
@bors try @rust-timer queue |
rust-timer
commented
May 11, 2021
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
bors
commented
May 11, 2021
⌛ Trying commit 17350de with merge 5d8726c5e6e2c8a635a0178c21932f6634271e89... |
bors
commented
May 11, 2021
☀️ Try build successful - checks-actions |
rust-timer
commented
May 11, 2021
Queued 5d8726c5e6e2c8a635a0178c21932f6634271e89 with parent 2bafe96, future comparison URL. |
rust-timer
commented
May 11, 2021
Finished benchmarking try commit (5d8726c5e6e2c8a635a0178c21932f6634271e89): comparison url. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up. @bors rollup=never |
SkiFire13
commented
May 11, 2021
Still pretty bad results |
the8472
commented
May 11, 2021
The clap-rs-opt full and clap-rs-opt incr-patched: println benchmarks still are spending additional time in llvm, as they did in the previous perf run. And they're way outside the noise level in the perf charts. So that's probably unrelated to Running that benchmark locally for master and for the branch and comparing the llvm-lines output might help. Maybe there are lots of generic instantiations of iterator code somewhere else. deeply-nested-async-opt incr-unchanged is interesting in a different way. It spends more time in rust passes, not llvm. That might be a genuine regression in iterator performance. Running that benchmark with |
…imulacrum replace vec::Drain drop loops with drop_in_place The `Drain::drop` implementation came up in rust-lang#82185 (comment) as potentially interfering with other optimization work due its widespread use somewhere in `println!` `@rustbot` label T-libs-impl
Dylan-DPC
commented
Mar 30, 2022
@SkiFire13 any updates on this? |
SkiFire13
commented
Mar 30, 2022
I left this PR in draft mode in case I got new ideas but nothing came up and eventually I forgot about it. |
replace vec::Drain drop loops with drop_in_place The `Drain::drop` implementation came up in rust-lang/rust#82185 (comment) as potentially interfering with other optimization work due its widespread use somewhere in `println!` `@rustbot` label T-libs-impl
This PR aims to improve the implementation of
IteratorandDoubleEndedIteratorfor&mut I where I: Iterator. This is accomplished by forwardingtry_foldto the implementation forI(since it takes&mut self) and implementingfoldin terms oftry_fold(sincefoldtakesself).Since
try_foldis not available ifI: !SizedI needed to specialize the caseI: Sized(that's also why I choose to keep the+ Sizedbound, to be explicit about what I'm specializing). This means this optimization won't apply to&mut dyn Iterator.While coding this pr I realized that it adds a considerable chunk of code for
&mut I where I: Iteratorand it may make sense to move it to a separate file just like other adapters. Tell me what you think about it.Edit: Note that the following benchmark results are relatively old (they were done before the LLVM 12 update for instance) and should probably be updated.
Here's a comparison (run with
cargo benchcmp master pr --threshold 2) of the benchmark (run withpy x.py bench --stage 0 library/core --test-args iter::):There are a lot of promising improvements, but surprisingly there are also a couple of strange regressions:
These benchmarks shouldn't have be impacted by my changes because they never use
&mut impl Iteratorbut somehow they were. My guess is that this is the result of some LLVM shenanigans because if I remove any benchmark containing.by_ref()then most of them don't regress anymore. Since these look like codegen problems and specific to the current benchmark I'm not too worried about them.These benchmarks however were directly impacted by my changes and the give the same results even if I remove all the other benchmarks, so I guess they're genuine regressions.
All these regressions are present even if I copy the default
foldimplementation but directly callI::nextinstead of passing through<&mut I>::next(which should just callI::nextanyway). This makes me think these are also codegen problem.I would like to not have these regressions but the other improvements probably outweights them.