-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Restore original implementation of Vec::retain #67300
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
This PR reverts rust-lang#48065, which aimed to optimize `Vec::retain` by making use of `Vec::drain_filter`. Unfortunately at that time, `drain_filter` was unsound. The soundness hole in `Vec::drain_filter` was fixed in rust-lang#61224 by guaranteeing that cleanup logic runs via a nested `Drop`, even in the event of a panic. Implementing this nested drop affects codegen (apparently?) and results in slower code. Fixes rust-lang#65970
(rust_highfive has picked a reviewer for you, use r? to override) |
r? @Gankra cc @rkruppe @alexcrichton |
r? @rkruppe This is unfortunate, but it does seem to generate better code (I haven't measured performance but the assembly is a lot closer to what it was 1.38) and the correctness of the old implementation was never in question so I can rubber-stamp it. @bors r+ |
📌 Commit 7ea6c46 has been approved by |
Restore original implementation of Vec::retain This PR reverts rust-lang#48065, which aimed to optimize `Vec::retain` by making use of `Vec::drain_filter`. Unfortunately at that time, `drain_filter` was unsound. The soundness hole in `Vec::drain_filter` was fixed in rust-lang#61224 by guaranteeing that cleanup logic runs via a nested `Drop`, even in the event of a panic. Implementing this nested drop affects codegen (apparently?) and results in slower code. Fixes rust-lang#65970
Rollup of 6 pull requests Successful merges: - #67255 (Remove i686-unknown-dragonfly target) - #67267 (Fix signature of `__wasilibc_find_relpath`) - #67282 (Fix example code of OpenOptions::open) - #67289 (Do not ICE on unnamed future) - #67300 (Restore original implementation of Vec::retain) - #67305 (Doc typo) Failed merges: r? @ghost
Optimize Vec::retain Use `copy_non_overlapping` instead of `swap` to reduce memory writes, like what we've done in rust-lang#44355 and `String::retain`. rust-lang#48065 already tried to do this optimization but it is reverted in rust-lang#67300 due to bad codegen of `DrainFilter::drop`. This PR re-implement the drop-then-move approach. I did a [benchmark](https://gist.github.com/oxalica/3360eec9376f22533fcecff02798b698) on small-no-drop, small-need-drop, large-no-drop elements with different predicate functions. It turns out that the new implementation is >20% faster in average for almost all cases. Only 2/24 cases are slower by 3% and 5%. See the link above for more detail. I think regression in may-panic cases is due to drop-guard preventing some optimization. If it's permitted to leak elements when predicate function of element's `drop` panic, the new implementation should be almost always faster than current one. I'm not sure if we should leak on panic, since there is indeed an issue (rust-lang#52267) complains about it before.
This PR reverts #48065, which aimed to optimize
Vec::retain
by making use ofVec::drain_filter
. Unfortunately at that time,drain_filter
was unsound.The soundness hole in
Vec::drain_filter
was fixed in #61224 by guaranteeing that cleanup logic runs via a nestedDrop
, even in the event of a panic. Implementing this nested drop affects codegen (apparently?) and results in slower code.Fixes #65970