Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
Speed up `nearest_common_ancestor`. #50106
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.
| @@ -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]; | |||
michaelwoerister
Apr 20, 2018
Contributor
Nice catch!
Nice catch!
210de11
to
cccd51c
|
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. |
|
This looks like the algorithm I wanted to do too -- thanks @nnethercote ! |
|
@bors r+ |
|
|
…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% ```
|
|
|
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:
|
|
@nagbot-rs: |
|
@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% ```
|
|
|
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_ancestorcan be made faster.Here are all the benchmarks where one of the measurements improved by at least 1%.