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

Remove pointer comparison check before doing memcmp #71735

Closed
wants to merge 2 commits into from

Conversation

samrat
Copy link
Contributor

@samrat samrat commented May 1, 2020

The hypothesis is that removing this pointer check will help improve performance since in most cases slices won't be compared with themselves.

Closes #71602

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 1, 2020
@samrat samrat changed the title Remove ptr comparison check before doing memcmp Remove pointer comparison check before doing memcmp May 1, 2020
@samrat
Copy link
Contributor Author

samrat commented May 1, 2020

The issue also mentions that this change needs to be benchmarked. From past PRs, it looks like I need to request @bors to queue a @rust-timer job. Shall I do that?

@tesuji
Copy link
Contributor

tesuji commented May 1, 2020

Only compiler team members can do that for you.

@jonas-schievink
Copy link
Contributor

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented May 1, 2020

⌛ Trying commit bcd3c1f with merge e992a97da01ade25fd0eab2f30d9c5fe0e3e1591...

@RalfJung
Copy link
Member

RalfJung commented May 1, 2020

Lol, this equality test has caused me much pain in Miri (not anymore, but it used to be a big problem)... and I never dared to question its existence. ;)

@bors
Copy link
Contributor

bors commented May 1, 2020

☀️ Try build successful - checks-azure
Build commit: e992a97da01ade25fd0eab2f30d9c5fe0e3e1591 (e992a97da01ade25fd0eab2f30d9c5fe0e3e1591)

@rust-timer
Copy link
Collaborator

Queued e992a97da01ade25fd0eab2f30d9c5fe0e3e1591 with parent bd0bacc, future comparison URL.

@Mark-Simulacrum
Copy link
Member

Presuming perf results are neutral (as I expect), I'm going to just go ahead with this; r? @Mark-Simulacrum

I believe that we don't need library (or compiler team) sign off for a change like this -- if our internal performance tests don't indicate a significant win, I'm going to suggest that it's likely not important enough to have for the vast majority of Rust programs, and it is known that it hurts some optimizations on the LLVM side.

I have confirmed that the case in #71602 is fixed by this PR locally -- both the functions in the issue description produce identical (and essentially optimal) codegen.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit e992a97da01ade25fd0eab2f30d9c5fe0e3e1591, comparison URL.

@tesuji
Copy link
Contributor

tesuji commented May 2, 2020

Debug builds seem to be regressed but that maybe just noise.

@RalfJung
Copy link
Member

RalfJung commented May 2, 2020

I have confirmed that the case in #71602 is fixed by this PR locally -- both the functions in the issue description produce identical (and essentially optimal) codegen.

Looks we we should have a codegen test then? These things regress very easily.

@bluss
Copy link
Member

bluss commented May 2, 2020

Would the biggest use case in favour of the current pointer equality check be map keys that are compared for equality? Long Vec/String/Box slice or whatever it is that bottoms out in this comparison.

More information about this change: #33892 (Use case: HTTP request parsing, it looks like)

  • Should the ptr equality check be used for some particular types? For example for &str, but not for short arrays?

@@ -5859,9 +5859,6 @@ where
if self.len() != other.len() {
Copy link
Member

Choose a reason for hiding this comment

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

(15 lines above) There's still a pointer comparison in the default fn equal, probably remove in both places, if the comparisons should be removed

@bluss
Copy link
Member

bluss commented May 2, 2020

@seanmonstar Is pointer equality check still a likely win, and for which comparisons?

@Mark-Simulacrum
Copy link
Member

@bluss I guess if you already have a copy of the map key (e.g. HashMap<&str, T>), then in theory yeah, this check could avoid the final string comparison. But if you already have exactly the key in the backing HashMap, it seems plausible to say you could also store a reference to the value too. (In theory, we could even provide a safe getter on HashMaps that provides the value given a pointer to a specific key, I think).

I agree that a codegen test would be nice, though I'm not sure how easy it would be.

I hadn't seen the http benchmarks before, if those are reproducible today (can test using the try build above, via rustup-toolchain-install-master), that would be somewhat convincing to me. Though if it's really such a big improvement, I'd guess there's value in interning or other optimizations that would permit going further or at least always hitting the optimization?

@samrat
Copy link
Contributor Author

samrat commented May 2, 2020

Added a codegen test for this.

@Mark-Simulacrum
Copy link
Member

I'm going to mark as S-blocked as I would like for either @seanmonstar to respond with how relevant this is to hyper or for someone to try and run some benchmarks similar to what was noted in #33892 (comment)

@Mark-Simulacrum Mark-Simulacrum added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 5, 2020
@seanmonstar
Copy link
Contributor

In http, we eventually made all the common constants be internal enum variants. I suspect this still affects if you were to compare them to strings (req.method() == "PATCH").

Is there a simple-ish way I could test with and without the pointer check in current nightly? Before the original PR was merged, I could do the pointer check manually and run benchmarks...

@Mark-Simulacrum
Copy link
Member

You should be able to do something like:

cargo install rustup-toolchain-install-master
rustup-toolchain-install-master bd0bacc694d7d8175804bb6f690cb846bfa4a9ee -n old
rustup-toolchain-install-master e992a97da01ade25fd0eab2f30d9c5fe0e3e1591 -n new
cargo +old bench
cargo +new bench

where bench can be run or whatever, of course.

@Mark-Simulacrum
Copy link
Member

Though I guess that we still haven't updated this to remove the pointer comparison in the default (non-memcmp case) but I suspect for hyper it probably doesn't matter too much? We should probably test both.

@bors
Copy link
Contributor

bors commented Jun 23, 2020

☔ The latest upstream changes (presumably #73643) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC-zz
Copy link

After a discussion with the reviewer, closing this pr as there is no further progress or momentum on this. If you wish, you can make a new pr that addresses this issue if there's a better way possible of approaching this. Thanks for taking the time to contribute :)

@Dylan-DPC-zz Dylan-DPC-zz added S-blocked-closed and removed S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. labels Aug 9, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 26, 2020
This resurrects rust-lang#71735.

Fixes rust-lang#71602, helps with rust-lang#80140.

r? `@Mark-Simulacrum`
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 26, 2020
Remove pointer comparison from slice equality

This resurrects rust-lang#71735.

Fixes rust-lang#71602, helps with rust-lang#80140.

r? `@Mark-Simulacrum`
@jyn514 jyn514 added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-blocked-closed labels Mar 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suboptimal generated code for testing that a &[u8; 4] contains all zeros