How to speed up the Rust compiler some more in 2020
blog.mozilla.org
blog.mozilla.org
For most people, knowing that the relevant people (in this case the Rust team) agree with your problem and are doing something about it significantly reduces the pain of the problem, because you know it's getting better. You need both parts though - the Rust team could be quietly working on performance for years and double compile speed and I probably wouldn't notice. This blog series is excellent marketing for some forward progress, and means that I do notice, and feel better about it.
I know the Rust contributors are doing their best, and that this blog post is not writing a marketing ploy, but in the end, the result is what matters.
My take on this is that I am fine with compile times as long as some effort is being done to keep it near optimal.
But I really do not want the Rust team to feel pressure to improve the compile times so much that they will end up killing other features or designing the language differently just for that (like Go, for instance). Or even making the compiler so complex that adding new features is harder for them.
I really like Rust as a language that is more complex to write and to compile but in return gives you robustness and performance. Compilation times be damned. I am not writing Rust to compile fast!
Year after year, people keep saying this or things like it. But it's worth remembering that it is not the compiler that makes your code fast, but how you structure your data transformations that makes code fast. In 2014, Mike Acton taught us that the best compiler optimisations can only account for 1-10% of the performance optimisation problem space. "The vast majority of [performance] problems, are problems the compiler cannot reason about." https://youtu.be/rX0ItVEVjHc?t=2097
Re-ordering of reads and writes is not really the problem either, even if we assume that one could automatically safely reorder reads and writes arbitrarily to yield significant optimisations. Fundamentally, the compiler does not know the semantics of your data and the relationships between pieces of data and the logic of their transformations. Knowledge of your specific problem and the specific data you are transforming yields the majority of the powerful optimisation opportunities. Similarly, a garbage collector doesn't know the meaning of your data or your algorithms.
> Is that really true in all cases though?
Consider: Given a set of data, if a compiler or garbage collector understood the data sufficiently, then there would be no need for you to exist to write the program, because the compiler could simply write the data transformations itself and generate the program.
However, one is encouraged to do experiments for oneself. Concrete profiling data, not abstract theory, is what matters when evaluating cost-benefit of any approach.
"The less you intend to do about something, the more you have to talk about it." However this maxim is not applicable here because compile times actually have been improving.
There is definitely a marketing angle to these posts. Rust has a reputation for slow compilation, and one of my goals is to show that (a) people working on Rust care about compile times, and (b) improvements are being made.
I'll let you judge whether the marketing is backed by actual substance. It's a long-running blog post series, here are links to all the posts.
* https://blog.mozilla.org/nnethercote/2016/10/14/how-to-speed...
* https://blog.mozilla.org/nnethercote/2016/11/23/how-to-speed...
* https://blog.mozilla.org/nnethercote/2018/04/30/how-to-speed...
* https://blog.mozilla.org/nnethercote/2018/06/05/how-to-speed...
* https://blog.mozilla.org/nnethercote/2018/11/06/how-to-speed...
* https://blog.mozilla.org/nnethercote/2019/07/17/how-to-speed...
* https://blog.mozilla.org/nnethercote/2019/07/25/the-rust-com...
* https://blog.mozilla.org/nnethercote/2019/10/11/how-to-speed...
* https://blog.mozilla.org/nnethercote/2019/12/11/how-to-speed...
* https://blog.mozilla.org/nnethercote/2020/04/24/how-to-speed...
* https://blog.mozilla.org/nnethercote/2020/08/05/how-to-speed...
EDIT: I just saw that alilleybrinker already linked to all these and more below: https://news.ycombinator.com/item?id=24061346
I was just today discussing with clang's code owner the idea of lazy parsing for static inline functions.
>slowdowns due to inline asm and sillyness in LLVM
I just hope that isn't a Chesterton's fence
My understanding is that compile times can be greatly improved simply by using a faster (and less optimising) code-generator, even without doing the (presumably much harder) work of optimising Rust's borrower-checker.
Disclaimer: I don't know all that much about Rust.
If both compilers are relatively bug-free it shouldn't be too much of a burden. Correct C/C++ code runs fine under both GCC and Clang, for example. If anything, things should be easier with Rust, as it gives you less opportunity to shoot yourself in the foot in strange compiler-specific ways than do C and C++. I recall having a C++ alignment issue that only arose in one compiler, for example. (Of course, my code was broken, but it worked ok with one of the compilers just 'by coincidence'.) I figure that kind of thing is less likely in Rust, but I don't know the Rust language well enough to say this with confidence.
This isn't to say that template errors are problem-free but the situation is much better than it was 5 years ago.
Java is my daily professional development. That's the baseline. And it's errors are not good as Rust's.
I often joke that IntelliJ IDEA is better programmer than I am. But in Rust, the same can be said of the Rust compiler.
The amount of suggestions, and explanations is stellar.
Ie, i tried out Diesel for a few projects and after several months, i'm moving away from it. The compiler messages can be insane due to Diesel's rather.. excessive use of generics haha.
SQLx has been really nice so far. I recommend it.
I've been writing in Rust in a very on-and-off fashion and thanks to the compiler messages I'm able to pick up where I left even after a few months.
All that while being a front-end developer or, in other words, as far removed from systems programming as possible.
I really appreciate the work described here, but it seems to me that the performance tests are in exactly the wrong place. The correct time to benchmark a PR is before it is merged; not after. It's the same for any other kind of test; your tests should pass before you merge, not after.
Sure, there will be exceptions where a performance regression is appropriate. But that should be known and agreed on before merging it.
I don't see a strong reason that the performance tests have to be done afterwards. I presume that it's okay to have a delay between creating the pull request and its merge, since humans will typically want to be able to review it!
Rust is very good about testing before merge, not after. It somewhat pioneered doing complete testing before merge (at least, built significant tooling and mind-share around doing it): https://graydon2.dreamwidth.org/1597.html https://bors.tech/
That is to say, if Rust isn't validating something pre-merge, it's more likely than not that there's a good reason for doing so. I don't personally know the reason for Rust, but, for performance testing in general, it's easy to overwhelm infrastructure because benchmarks should be being run on a single physical machine that's otherwise quiet. This means that testing is completely serialised and there's no opportunity for parallelism. Based on https://perf.rust-lang.org/status.html , it looks like the performance tests currently take a bit longer than an hour each.
As others have mentioned, there's automatic tooling for running tests on PRs that may be performance sensitive, and PRs are reverted if they accidentally cause a regression, to be able to reset and reanalyse.
If it's slower, then you require a manual override to accept the merge.
That will make performance regressions a whole lot less likely. Sure, in some cases they may be necessary, but in many cases they were unintentional; they can be fixed, and then merged.
[0]: https://github.com/rust-lang/rust/pulls?q=is%3Apr+is%3Amerge...
[1]: https://github.com/rust-lang/rust/pulls?q=is%3Apr+is%3Amerge...
Most changes are not going to change the compiler performance. Better to watch a trend line and revert any change that hurts performance in a significant way. Releases are every 6 weeks so there is plenty of time for this type of analysis and activity.
When I'm scrolling then section titles like 'Weekly performance triage' have green border for a like 0.5sec.
[0] https://nikic.github.io/2020/05/10/Make-LLVM-fast-again.html
* 2020-08-05: "How to Speed Up the Rust Compiler Some More in 2020" https://blog.mozilla.org/nnethercote/2020/08/05/how-to-speed-up-the-rust-compiler-some-more-in-2020/ (this post)
* 2020-04-04: "How to Speed Up the Rust Compiler in 2020" https://blog.mozilla.org/nnethercote/2020/04/24/how-to-speed-up-the-rust-compiler-in-2020/
* 2019-12-11: "How to Speed Up the Rust Compiler One Last Time in 2019" https://blog.mozilla.org/nnethercote/2019/12/11/how-to-speed-up-the-rust-compiler-one-last-time-in-2019/
* 2019-10-11: "How to Speed Up the Rust Compiler Some More in 2019" https://blog.mozilla.org/nnethercote/2019/10/11/how-to-speed-up-the-rust-compiler-some-more-in-2019/
* 2019-07-17: "How to Speed Up the Rust Compiler in 2019" https://blog.mozilla.org/nnethercote/2019/07/17/how-to-speed-up-the-rust-compiler-in-2019/
* 2019-06-25: "The Rust Compiler is Still Getting Faster" https://blog.mozilla.org/nnethercote/2019/07/25/the-rust-compiler-is-still-getting-faster/
* 2018-11-06: "How to Speed Up the Rust Compiler in 2018: NLL Edition" https://blog.mozilla.org/nnethercote/2018/11/06/how-to-speed-up-the-rust-compiler-in-2018-nll-edition/
* 2018-06-05: "How to Speed Up the Rust Compiler Some More in 2018" https://blog.mozilla.org/nnethercote/2018/06/05/how-to-speed-up-the-rust-compiler-some-more-in-2018/
* 2018-05-17: "The Rust Compiler is Getting Faster" https://blog.mozilla.org/nnethercote/2018/05/17/the-rust-compiler-is-getting-faster/
* 2018-04-30: "How to Speed Up the Rust Compiler in 2018" https://blog.mozilla.org/nnethercote/2018/04/30/how-to-speed-up-the-rust-compiler-in-2018/
* 2016-11-23: "How to Speed Up the Rust Compiler Some More" https://blog.mozilla.org/nnethercote/2016/11/23/how-to-speed-up-the-rust-compiler-some-more/
* 2016-10-14: "How to Speed Up the Rust Compiler" https://blog.mozilla.org/nnethercote/2016/10/14/how-to-speed-up-the-rust-compiler/ (the post that started it all!)
He's also written about tools and concepts for crate maintainers to understand and improve their own compile-times: * 2019-10-10: "Visualizing Rust Compilation" https://blog.mozilla.org/nnethercote/2019/10/10/visualizing-rust-compilation/
* 2018-11-09: "How to get the size of Rust types with `-Zprint-type-sizes`" https://blog.mozilla.org/nnethercote/2018/11/09/how-to-get-the-size-of-rust-types-with-zprint-type-sizes/
* 2018-07-24: "Ad Hoc Profiling" https://blog.mozilla.org/nnethercote/2018/07/24/ad-hoc-profiling/
He's also contributed to useful profiling tooling! * 2019-04-19: "A Better DHAT" https://blog.mozilla.org/nnethercote/2019/04/17/a-better-dhat/
All this to say: huge thank you to Nicholas, and if you're interested in learning how to do real-world performance work, these posts are an excellent resource!