Uh oh!
There was an error while loading. Please reload this page.
core: check for pointer equality when comparing Eq slices - #61665
Conversation
Because Eq types must be reflexively equal, an equal-length slice to the same memory location must be equal.
rust-highfive
commented
Jun 8, 2019
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @sfackler (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
| return true; | ||
| } | ||
| for i in 0..self.len() { |
There was a problem hiding this comment.
This could be written as:
self.iter().zip(other.iter()).all(|(x, y)| x == y)There was a problem hiding this comment.
Good point. I mindlessly copied the other impl, but as written it's not clear the bounds check for other[i] would always be elided. I've updated both impls to user iterators now.
oli-obk
commented
Jun 8, 2019
@bors try |
bors
commented
Jun 8, 2019
⌛ Trying commit 30b27f3 with merge 7966b55e0c690a4bce499ac9179ac54610f3cb66... |
bors
commented
Jun 8, 2019
⌛ Trying commit 30b27f3 with merge 034cf602489c17a0d3a6b9991f6a3997bf23d56d... |
aschampion
commented
Jun 9, 2019
|
Centril
commented
Jun 10, 2019
@bors try |
bors
commented
Jun 10, 2019
⌛ Trying commit d482589 with merge 261715133edddbeeccb64c5a890ce76658fe589f... |
bors
commented
Jun 10, 2019
☀️ Try build successful - checks-travis |
Centril
commented
Jun 10, 2019
@rust-timer build 261715133edddbeeccb64c5a890ce76658fe589f |
rust-timer
commented
Jun 10, 2019
Success: Queued 261715133edddbeeccb64c5a890ce76658fe589f with parent 400b409, comparison URL. |
rust-timer
commented
Jun 10, 2019
Finished benchmarking try commit 261715133edddbeeccb64c5a890ce76658fe589f, comparison URL. |
sfackler
commented
Jun 10, 2019
Either way - a separate PR may be best to avoid accidentally dropping the change if the perf run reports that the pointer equality check isn't worth it though. |
core: use memcmp optimization for 128 bit integer slices All other sized integer slices do this. From rust-lang#61665.
core: use memcmp optimization for 128 bit integer slices All other sized integer slices do this. From rust-lang#61665.
core: use memcmp optimization for 128 bit integer slices All other sized integer slices do this. From rust-lang#61665.
Dylan-DPC-zz
commented
Jul 1, 2019
ping from triage @sfackler@aschampion any updates on this? |
sfackler
commented
Jul 1, 2019
The benchmark results seem like a pretty mixed bag - not sure if this change really had much of an impact. |
aschampion
commented
Jul 2, 2019
For context, I created this because I had code (change queue consistency check) where the most common path was same slice comparison, and having exploited the primitive slice equal pointer optimization before was surprised when the performance was linear and not constant. Of course, if you want to rely on this optimization it's easy to manually check for this case, which is what I've done in the meantime. However, it doesn't look like this comes up frequently in the benchmarking suite. I've looked through a few popular crates trying to find cases where this would apply, but haven't found any yet. So it's down to whether having behavior consistent with primitive slices is seen as more consistent/less surprising, or if having another |
sfackler
commented
Jul 2, 2019
Yeah, that all makes sense - seems like it's worth discussing at the next libs triage meeting. |
sfackler
commented
Jul 10, 2019
We talked about this at the libs meeting today, and tentatively felt like we should land this. It doesn't appear to regress normal code in a significant way, and we can always back it out later! @bors r+ |
bors
commented
Jul 10, 2019
📌 Commit d482589 has been approved by |
core: check for pointer equality when comparing Eq slices Because `Eq` types must be reflexively equal, an equal-length slice to the same memory location must be equal. This is related to rust-lang#33892 (and rust-lang#32699) answering this comment from that PR: > Great! One more easy question: why does this optimization not apply in the non-BytewiseEquality implementation directly above? Because slices of non-reflexively equal types (like `f64`) are not equal even if it's the same slice. But if the types are `Eq`, we can use this same-address optimization, which this PR implements. Obviously this changes behavior if types violate the reflexivity condition of `Eq`, because their impls of `PartialEq` will no longer be called per-item, but 🤷♂ . It's not clear how often this optimization comes up in the real world outside of the same-`&str` case covered by rust-lang#33892, so **I'm requesting a perf run** (on MacOS today, so can't run `rustc_perf` myself). I'm going ahead and making the PR on the basis of being surprised things didn't already work this way. This is my first time hacking rust itself, so as a perf sanity check I ran `./x.py bench --stage 0 src/lib{std,alloc}`, but the differences were noisy. To make the existing specialization for `BytewiseEquality` explicit, it's now a supertrait of `Eq + Copy`. `Eq` should be sufficient, but `Copy` was included for clarity.
Rollup of 7 pull requests Successful merges: - #61665 (core: check for pointer equality when comparing Eq slices) - #61923 (Prerequisites from dep graph refactoring #2) - #62270 (Move async-await tests from run-pass to ui) - #62425 (filedesc: don't use ioctl(FIOCLEX) on Linux) - #62476 (Continue refactoring macro expansion and resolution) - #62519 (Regression test for HRTB bug (issue 30786).) - #62557 (Fix typo in libcore/intrinsics.rs) Failed merges: r? @ghost
bors
commented
Jul 11, 2019
bors
commented
Jul 11, 2019
☔ The latest upstream changes (presumably #62580) made this pull request unmergeable. Please resolve the merge conflicts. |
Because
Eqtypes must be reflexively equal, an equal-length slice to the same memory location must be equal.This is related to #33892 (and #32699) answering this comment from that PR:
Because slices of non-reflexively equal types (like
f64) are not equal even if it's the same slice. But if the types areEq, we can use this same-address optimization, which this PR implements. Obviously this changes behavior if types violate the reflexivity condition ofEq, because their impls ofPartialEqwill no longer be called per-item, but 🤷♂ .It's not clear how often this optimization comes up in the real world outside of the same-
&strcase covered by #33892, so I'm requesting a perf run (on MacOS today, so can't runrustc_perfmyself). I'm going ahead and making the PR on the basis of being surprised things didn't already work this way.This is my first time hacking rust itself, so as a perf sanity check I ran
./x.py bench --stage 0 src/lib{std,alloc}, but the differences were noisy.To make the existing specialization for
BytewiseEqualityexplicit, it's now a supertrait ofEq + Copy.Eqshould be sufficient, butCopywas included for clarity.