-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Improve memoization and refactor NLL type check #51460
Improve memoization and refactor NLL type check #51460
Conversation
We used to accumulate a vector of type-check constraints, but now we generate them as we go, and just store the NLL-style `OutlivesConstraint` and `TypeTest` information.
The choice is arbitrary since there is only one involved.
Resetting unifications is expensive. Only do if there is something to reset.
…r=<try> Improve memoization and refactor NLL type check I have a big branch that is refactoring NLL type check with the goal of introducing canonicalization-based memoization for all of the operations it does. This PR contains an initial prefix of that branch which, I believe, stands alone. It does introduce a few smaller optimizations of its own: - Skip operations that are trivially a no-op - Cache the results of the dropck-outlives computations done by liveness - Skip resetting unifications if nothing changed r? @pnkfelix
Perf queued. |
💥 Test timed out |
Perf result is great for those that can be compiled. The timings for futures and serde are missing though. |
Compilation failures for serde/futures: Serde
futures
|
Interesting. Thanks! |
(FYI I plan to start my review on Tuesday June 12th) |
Minimized failure: struct Map<A, F> where A: Future {
a: A,
f: F,
}
trait Future {
type Item;
type Error;
fn tailcall(&mut self) -> Option<Box<Future<Item=Self::Item, Error=Self::Error>>>;
}
impl<A, F, U> Future for Map<A, F>
where
A: Future,
F: FnOnce(A::Item) -> U + Send + 'static,
U: Send + 'static,
{
type Item = U;
type Error = A::Error;
fn tailcall(&mut self)
-> Option<Box<Future<Item=Self::Item, Error=Self::Error>>> {
None
}
}
fn main() {} I found the bug, it is a pre-existing weirdness in the NLL checker that I have to think about the best way to fix. =) |
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.
just from skimming 956e2f8 I'll just say it would be nice if the rustfmt
runs were isolated to their own commits...)
((I am now experimenting with "ignore whitespace changes" to try to deal with this...))
(((oh, apparently there are commits that are factored out rustfmt
runs. maybe 956e2f8 is just the result of IDE auto-indent...)))
The PR seems fine from what I saw. (Obviously I must have missed something since there is the aforementioned bug that niko is working on.) |
@bors r+ |
📌 Commit 2e25bed has been approved by |
…r=pnkfelix Improve memoization and refactor NLL type check I have a big branch that is refactoring NLL type check with the goal of introducing canonicalization-based memoization for all of the operations it does. This PR contains an initial prefix of that branch which, I believe, stands alone. It does introduce a few smaller optimizations of its own: - Skip operations that are trivially a no-op - Cache the results of the dropck-outlives computations done by liveness - Skip resetting unifications if nothing changed r? @pnkfelix
☀️ Test successful - status-appveyor, status-travis |
This gave some big perf wins for NLL perf, but also lots of smaller improvements for non-NLL builds: Nice work. cc @rust-lang/wg-compiler-performance |
[WIP] Convert NLL ops to caches This is a extension of <#51460>. It uses a lot more caching than we used to do. This caching is not yet as efficient as it could be, but I'm curious to see the current perf results.
convert NLL ops to caches This is a extension of <#51460>. It uses a lot more caching than we used to do. This caching is not yet as efficient as it could be, but I'm curious to see the current perf results. This is the high-level idea: in the MIR type checker, use [canonicalized queries](https://rust-lang-nursery.github.io/rustc-guide/traits/canonical-queries.html) for all the major operations. This is helpful because the MIR type check is operating in a context where all types are fully known (mostly, anyway) but regions are completely renumbered. This means we often wind up with duplicate queries like `Foo<'1, '2> :Bar` and `Foo<'3, '4>: Bar`. Canonicalized queries let us re-use the results. By the final commit in this PR, we can essentially just "read off" the resulting region relations and add them to the NLL type check.
I have a big branch that is refactoring NLL type check with the goal of introducing canonicalization-based memoization for all of the operations it does. This PR contains an initial prefix of that branch which, I believe, stands alone. It does introduce a few smaller optimizations of its own:
r? @pnkfelix