Closed
Description
1.57.0 seems to have brought a pretty deep regression in compile times for deeply nested "decorator" types, such as futures' Stream
combinators.
This is a minimized version of kube-rs/kube#746.
Code
I tried this code:
use futures::{stream, StreamExt, TryStreamExt};
fn main() {
stream::empty::<Result<(), ()>>()
.inspect_ok(|_| ())
.inspect_ok(|_| ())
// .boxed()
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
// .boxed()
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ())
// .boxed()
.inspect_ok(|_| ())
.inspect_ok(|_| ())
.inspect_ok(|_| ());
}
In Rust 1.56.1, this builds in ~0.7s on my machine (excluding time spent compiling futures
and its dependencies).
In Rust 1.57.0 (and the latest nightly), this takes several minutes.
Curiously, boxing into a trait object (by uncommenting the .boxed()
calls) seems to act as a type checking boundary, and makes rustc 1.57.0 build it in ~0.55s.
Version it worked on
It most recently worked on: Rust 1.56.1
Version with regression
rustc --version --verbose
:
rustc 1.57.0 (f1edd0429 2021-11-29)
Backtrace
There was no crash, so there is no backtrace to report.
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
nightkr commentedon Dec 6, 2021
RUSTC_BOOTSTRAP=1 cargo rustc -- -Z new-llvm-pass-manager=no
does not seem to make a difference, so this seems unrelated to #91128.SNCPlay42 commentedon Dec 6, 2021
Sounds like #89195/#89601.
the8472 commentedon Dec 6, 2021
It builds in 11 seconds with #91186 (tested with build 1937cf62d0cb08000a49346c146830a7de817de3)
nightkr commentedon Dec 6, 2021
Can confirm that #91186 brings my build time for the listed example down to ~9s. So it's a vast improvement over 1.57.0, but still 13x the compile time of 1.56.1.
xmo-odoo commentedon Dec 7, 2021
I may have also hit that in a project of mine (currently only on my machine), initially was thinking "oh it's probably serde" as there are a ton of large serde-enabled types in the project, but this is also a project based on warp and that is very much a "deeply nested decorator types" framework.
Here are the compile time (from clean, but in 1.57 the vast, vast majority of the time is spent building the final binary which is where all the warp code lives, hence the concurrency going to shit):
The project is only 2.7kLOC (of rust) so it's not exactly gigantic
After seeing https://old.reddit.com/r/rust/comments/qdivb5/156_compile_time_is_through_the_roof/ I tried to profile-dump the result, here it is (though it's nightly), warning it's quite long but the problematic item is clearly
evaluate_obligation
(I have no idea what that is) as it takes 400s and >80% of the profile.For refernce, here is what I guess is my current nightly, and how long the clean build takes on it without profiling:
so seems slightly better, but the regression is still there (the slightly lower average load might be due to other activities, or a sign that the regression got worse but other bits more than compensated for it).
-Z self-profile dump
apiraino commentedon Dec 7, 2021
I've put together a small reproducible project for the Warp web framework case (which seems to be specifically hit by this regression as @xmo-odoo correctly mentions). It's not exactly the MCVE I wish I could provide, hopefully it's a good start.
https://github.com/apiraino/test-regression-157
Time spent compiling is comparable in both 1.56.1 and 1.57.0. Linking is where the regression is apparent.
In case it's relevant here's the compile/link flags:
xmo-odoo commentedon Dec 7, 2021
FWIW I tested #91186 locally (thanks @teozkr for their help building and installing rustc from a pr) and it seems to more or less fix the regression for me:
there's a marginal slowdown (it's a bit slower than 1.55 while using a larger %cpu, and a good 50s more USER CPU time, possibly because it's only a stage 1 compiler?) but it mostly resolves the issue.
28 remaining items