-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Speed up nearest_common_ancestor
.
#50106
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
Conversation
This code path is rarely hit, which likely explains why this bug hasn't been detected before now. (I only noticed it via code inspection.)
`nearest_common_ancestor()` uses an algorithm that requires computing the full scope chain for both scopes, which is expensive because each element involves a hash table lookup, and then looking for a common tail. This patch changes `nearest_common_ancestor()` to use a different algorithm, which starts at the given scopes and works outwards (i.e. up the scope tree) until a common ancestor is found. This is much faster because in most cases the common ancestor is found well before the end of the scope chains. Also, the use of a SmallVec avoids the need for any allocation most of the time.
src/librustc/middle/region.rs
Outdated
@@ -706,7 +706,7 @@ impl<'tcx> ScopeTree { | |||
// "Modeling closures" section of the README in | |||
// infer::region_constraints for more details. | |||
let a_root_scope = a_ancestors[a_index]; | |||
let b_root_scope = a_ancestors[a_index]; | |||
let b_root_scope = b_ancestors[b_index]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch!
210de11
to
cccd51c
Compare
Thanks, @nnethercote! I think @nikomatsakis had some ideas on how to exploit some domain knowledge to speed this. He probably should take a look at this. |
Here are things I've found from my measurements:
I'm not satisfied with the representation of |
I've done some work on this, and I haven't yet managed to make things any faster with the new representation. So I think it's definitely worth evaluating this PR as is. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like the algorithm I wanted to do too -- thanks @nnethercote !
@bors r+ |
📌 Commit cccd51c has been approved by |
⌛ Testing commit cccd51c with merge 38eb9cd0bc367e95e227fa8bafec95940acf8823... |
💔 Test failed - status-appveyor |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
This looks like an infrastructure failure. Can someone please retry? |
@bors: retry
* crates.io was down
…On Tue, Apr 24, 2018 at 7:52 PM, bors ***@***.***> wrote:
💔 Test failed - status-appveyor
<https://ci.appveyor.com/project/rust-lang/rust/build/1.0.7131>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#50106 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AaPN0C5s5zxNU9kkd7L0ES0DWk2vGJZaks5tr8jOgaJpZM4TdO2p>
.
--
You received this message because you are subscribed to the Google Groups
"rust-ops" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to ***@***.***
To post to this group, send email to ***@***.***
To view this discussion on the web visit https://groups.google.com/d/
msgid/rust-ops/rust-lang/rust/pull/50106/c384125552%40github.com
<https://groups.google.com/d/msgid/rust-ops/rust-lang/rust/pull/50106/c384125552%40github.com?utm_medium=email&utm_source=footer>
.
For more options, visit https://groups.google.com/d/optout.
|
@nagbot-rs: 🔑 Insufficient privileges: not in try users |
@bors: retry |
…sakis Speed up `nearest_common_ancestor`. `nearest_common_ancestor` can be made faster. Here are all the benchmarks where one of the measurements improved by at least 1%. ``` clap-rs-check avg: -4.5% min: -8.8% max: -0.3% clap-rs avg: -2.6% min: -4.5% max: 0.5% script-servo avg: -1.7% min: -3.6% max: 0.0% regression-31157 avg: -1.5% min: -2.6% max: -0.4% hyper avg: -1.2% min: -2.5% max: -0.0% piston-image avg: -1.6% min: -2.5% max: 0.1% regex avg: -1.2% min: -2.2% max: 0.0% issue-46449 avg: -1.8% min: -2.1% max: -0.7% crates.io avg: -1.2% min: -2.1% max: 0.0% hyper-check avg: -1.0% min: -2.1% max: -0.1% clap-rs-opt avg: -1.4% min: -2.0% max: -0.3% piston-image-check avg: -1.2% min: -1.9% max: -0.1% regex-check avg: -0.5% min: -1.8% max: -0.1% syn avg: -1.1% min: -1.7% max: -0.1% tokio-webpush-simple-check avg: -1.1% min: -1.6% max: -0.3% tokio-webpush-simple avg: -1.2% min: -1.6% max: -0.0% helloworld-check avg: -1.4% min: -1.6% max: -1.2% deeply-nested avg: -1.2% min: -1.4% max: -0.8% encoding-check avg: -0.8% min: -1.3% max: -0.3% unify-linearly-check avg: -1.0% min: -1.3% max: -0.8% script-servo-check avg: -0.6% min: -1.3% max: 0.0% regression-31157-check avg: -0.9% min: -1.2% max: -0.7% script-servo-opt avg: -0.5% min: -1.2% max: 0.1% deeply-nested-check avg: -0.8% min: -1.2% max: -0.7% encoding avg: -0.7% min: -1.1% max: -0.3% issue-46449-check avg: -0.9% min: -1.1% max: -0.6% parser-check avg: -0.9% min: -1.1% max: -0.8% html5ever avg: -0.5% min: -1.0% max: -0.0% ```
☀️ Test successful - status-appveyor, status-travis |
Two remarks :
|
I did try a hash table. SmallVec was slightly faster for the rustc-perf suite. Two Vecs would halve the number of comparisons, but it would require an extra heap allocation. I don't know which effect would be greater. |
Another option is to maintain a single |
And actually I expect 2 SmallVecs to be a win, considering they are stack-allocated most of the time. |
nearest_common_ancestor
can be made faster.Here are all the benchmarks where one of the measurements improved by at least 1%.