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

perf: Reuse the Elaborator used in outlives/ty.rs #67840

Closed
wants to merge 5 commits into from

Conversation

Marwes
Copy link
Contributor

@Marwes Marwes commented Jan 3, 2020

The first commit mostly cleans up some unnecessary allocations (I wouldn't expect it to change runtime noticeably).

The second commit should improve things a bit however.

Profiling the build of https://github.com/Marwes/combine shows that
~1.3% of the time were spent resizing and rehashing the hash set used in
Elaborator. By reusing the Elaborator between calls this should
be mostly eliminated.

It does result in some awkwardness since the RefCell needs to be
borrowed in the returned Iterator but it works fine for the current
code.

@rust-highfive
Copy link
Collaborator

r? @cramertj

(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 Jan 3, 2020
@Centril
Copy link
Contributor

Centril commented Jan 3, 2020

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Jan 3, 2020

⌛ Trying commit 9d3525cb9e193ff6622382ca97d0ff5ccfe00a6f with merge 1914befff0a7286add08d15ce8bd162c479d12ea...

@bors
Copy link
Contributor

bors commented Jan 3, 2020

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

@rust-timer
Copy link
Collaborator

Queued 1914befff0a7286add08d15ce8bd162c479d12ea with parent 30ddb5a, future comparison URL.

@Marwes
Copy link
Contributor Author

Marwes commented Jan 4, 2020

Storing it directly in VerifyBoundCx didn't help since that struct gets thrown away between calls. Moving it out a bit should hopefully show results (testing locally now as well). Could perhaps store the Elaborator in InferCtxt as well for more reuse but I don't know if that is an acceptable place for it.

The need for Captures2/3 was really confusing but it was the only way I could get the lifetimes to work out...

@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 Jan 5, 2020

⌛ Trying commit ef010deb93eaa3a1b54b77662e08a3a50b0a37be with merge 5d370d4923feb2e292d66958a4fba07d6b95e788...

bors added a commit that referenced this pull request Jan 5, 2020
perf: Avoid re-interning types in outlives checking

In profiling `intern_ty` is a very hot function (9% in the test I used). While there does not seem to be a way to reduce the cost of calling we can avoid the call in some cases.

In outlives checking `ParamTy` and `ProjectionTy` are extracted from the `Ty` value that contains them only to later be passed as an argument to `intern_ty` again later. This seems to be happening a lot in my test with `intern_ty` called from outlives is at ~6%.

Since all `ParamTy` and `ProjectionTy` are already stored in a `Ty` I had an idea to pass around a `View` type which provides direct access to the specific, inner type without losing the original `Ty` pointer. While the current implementation does so with some unsafe to let the branch be elided on `Deref`, it could be done entirely in safe code as well, either by accepting the (predictable) branch in `Deref` or by storing the inner type in `View` as well as the `Ty`. But considering that the unsafe is trivial to prove and the call sites seem quite hot I opted to show the unsafe approach first.

Based on #67840 (since it touches the same file/lines)

Commits without #67840 https://github.com/rust-lang/rust/pull/67899/files/77ddc3540e52be4b5bd75cf082c621392acaf81b..b55bab206096c27533120921f6b0c273f115e34a
@bors
Copy link
Contributor

bors commented Jan 5, 2020

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

@rust-timer
Copy link
Collaborator

Queued 5d370d4923feb2e292d66958a4fba07d6b95e788 with parent 7785834, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit 5d370d4923feb2e292d66958a4fba07d6b95e788, comparison URL.

@bors
Copy link
Contributor

bors commented Jan 6, 2020

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

Profiling the build of https://github.com/Marwes/combine shows that
~1.3% of the time were spent resizing and rehashing the hash set used in
`Elaborator`. By reusing the `Elaborator` between calls this should
be mostly eliminated.

It does result in some awkwardness since the `RefCell` needs to be
borrowed in the returned `Iterator` but it works fine for the current
code.
Avoids the risk of attempting to borrow `elaborator` twice by accident.

The need for `Captures2` is odd, but it seems like `impl Trait` kept
generating lifetime constraints that forced `'a` or `'cx` to be
identical to `'tcx` otherwise (due to `'tcx` being invariant I think).
@Marwes
Copy link
Contributor Author

Marwes commented Jan 6, 2020

Moved Elaborator up into InferCtxt which hopefully fixes the regression.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2020-01-06T19:31:59.8718317Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-01-06T19:31:59.8963057Z ##[command]git config gc.auto 0
2020-01-06T19:31:59.9032649Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-01-06T19:31:59.9086170Z ##[command]git config --get-all http.proxy
2020-01-06T19:31:59.9236903Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/67840/merge:refs/remotes/pull/67840/merge

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 @TimNN. (Feature Requests)

@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 Jan 6, 2020

⌛ Trying commit 365ccde with merge afcb9992e87f7467f8a42fcada070f570cdb9327...

@bors
Copy link
Contributor

bors commented Jan 6, 2020

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

@rust-timer
Copy link
Collaborator

Queued afcb9992e87f7467f8a42fcada070f570cdb9327 with parent ebbb2bf, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit afcb9992e87f7467f8a42fcada070f570cdb9327, comparison URL.

bors added a commit that referenced this pull request Jan 10, 2020
perf: Avoid re-interning types in outlives checking

In profiling `intern_ty` is a very hot function (9% in the test I used). While there does not seem to be a way to reduce the cost of calling we can avoid the call in some cases.

In outlives checking `ParamTy` and `ProjectionTy` are extracted from the `Ty` value that contains them only to later be passed as an argument to `intern_ty` again later. This seems to be happening a lot in my test with `intern_ty` called from outlives is at ~6%.

Since all `ParamTy` and `ProjectionTy` are already stored in a `Ty` I had an idea to pass around a `View` type which provides direct access to the specific, inner type without losing the original `Ty` pointer. While the current implementation does so with some unsafe to let the branch be elided on `Deref`, it could be done entirely in safe code as well, either by accepting the (predictable) branch in `Deref` or by storing the inner type in `View` as well as the `Ty`. But considering that the unsafe is trivial to prove and the call sites seem quite hot I opted to show the unsafe approach first.

Based on #67840 (since it touches the same file/lines)

Commits without #67840 https://github.com/rust-lang/rust/pull/67899/files/77ddc3540e52be4b5bd75cf082c621392acaf81b..b55bab206096c27533120921f6b0c273f115e34a
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 18, 2020
@JohnCSimon
Copy link
Member

Ping from triage: @Marwes can you please address the merge conflicts?

@jonas-schievink
Copy link
Contributor

The latest perf run still indicates a regression and no improvement. Is there a way to fix that or should this be closed?

@Marwes Marwes closed this Jan 18, 2020
@Marwes
Copy link
Contributor Author

Marwes commented Jan 18, 2020

Closing. Will try to figure out the regressions and resubmit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants