N
Nicholas Nethercote
nnethercote.github.io · Personal blog · on HN since 2020
Nicholas Nethercote, a Rust compiler contributor, writes about measuring and speeding up rustc and other Rust performance work.
What HN saysCommenters like his detailed, step-by-step optimization write-ups and cite his Rust Performance Book and logs of incremental compiler speedups.
65HN people shared it
34linked it in comments
54stories submitted
2.1Kstory points
3 months agolast shared
2020people per year2026
Most-shared posts
- 1The Rust Performance Book (2020)8 people · 400 points · first shared 2020 · 33 comments on HN
- 2Faster Rust Builds on Mac8 people · 29 points · first shared 2025 · 1 comments on HN
- 3A brutally effective hash function in Rust5 people · 10 points · first shared 2021 · discussion on HN
- 4How to speed up the Rust compiler in March 20235 people · 3 points · first shared 2023 · discussion on HN
- 5The Rust compiler has gotten faster again4 people · 200 points · first shared 2021 · 134 comments on HN
- 6How much code does that proc macro generate?4 people · 10 points · first shared 2025 · discussion on HN
- 7Back-end parallelism in the Rust compiler3 people · 4 points · first shared 2023 · 1 comments on HN
- 8Homepage3 people · first shared 2025
- 9Twenty years of Valgrind2 people · 849 points · first shared 2022 · 112 comments on HN
- 10The Rust Performance Book (2020)2 people · 194 points · first shared 2022 · 9 comments on HN
- 11How to speed up the Rust compiler in 20222 people · 174 points · first shared 2022 · 22 comments on HN
- 12How to speed up the Rust compiler in October 20222 people · 75 points · first shared 2022 · 10 comments on HN
- 13How to speed up the Rust compiler in April 20222 people · 74 points · first shared 2022 · 4 comments on HN
- 14How to speed up the Rust compiler in March 20242 people · 35 points · first shared 2024 · discussion on HN
- 15How to speed up the Rust compiler in December 20252 people · 27 points · first shared 2025 · 1 comments on HN
What HN people wrote when they linked it
zengid · 2026-05-31
I've been thinking a lot about a solution to Rust's notoriously slow compile times. From my research, it's not the borrow checker that is the issue, it's the heavy optimizations and monomorphization, and macro expansion [0]. There are efforts to improve Rust compile times, but I realized recently that it will never be lightning fast, so we (Rust users) should really be developing more scripting languages and DSLs that we can put all of the fiddly bits into.
Places where we would benefit the most from this is in the Games and UI space. I know game devs have already started by integrating lua, like with mlua [1]. In the UI space i think Makepad is the best example of a team making a dedicated DSL that can be hot-reloaded [2].
I think we need more of this! Go make a DSL next time you feel crushed by the weight of compiling Rust crates!
---
[0] and by my research i mean Claude. this is a great blog with many posts about improving compile times https://nnethercote.github.io/
[1] https://crates.io/crates/mlua . I don't have a reference for a project using it though so please reply if you know of one!
[2] https://github.com/makepad/makepad
mdf · 2025-05-22
There's something about real optimization stories that I find fascinating – particularly the detailed ones including step-by-step improvements and profiling to show how numbers got better. In some way, they are satisfying to read.
Nicholas Nethercote's "How to speed up the Rust compiler" writings[1] fall into this same category for me.
Any others?
[1] https://nnethercote.github.io/
gue5t · 2025-02-28
Personally I've been inspired by nnethercote's logs (https://nnethercote.github.io/) of incremental single-digit percentage performance improvements to rustc over the past several years. The serial portion of compilers is still quite significant and efforts to e.g. parallelize the entire rustc frontend are heroic slogs that have run into subtle semantic problems (deadlocks and races) that have made it very hard to land them. Not to disparage those working on that approach, but it is really difficult! Meanwhile, dozens of small speedups accumulate to really significant performance improvements over time.
fyzix · 2023-10-11
The rust solution is not using std hashmap. It using FXhashmap as recommended by the rust perf book: https://nnethercote.github.io/perf-book/hashing.html
n8ta · 2023-07-25
alpaca128 · 2021-04-25
My favorite is still the Rust Container Cheat Sheet[0] from the Rust Performance Book[1]. Great overview on just one page - that's what I call a cheat sheet.
Edit: Also recommended: The Little Book of Rust Macros[2]
[0] https://docs.google.com/presentation/d/1q-c7UAyrUlM-eZyTo1pd8SZ0qwA_wY…
[1] https://nnethercote.github.io/perf-book/title-page.html
[2] https://veykril.github.io/tlborm/introduction.html
mswphd · 2026-05-27
for context: in rust the "translation unit" is a crate (in C++, each source file is its own translation unit). So you only get parallelism across crates when compiling in rust. When you have a single-crate project, this means that
1. you get parallelism across all your dependencies, but
2. your (final) crate is serial.
Splitting your crate can therefore get you parallelism back in step 2, which can be a (compilation) perf win. You can also get a caching benefit when there aren't changes, but even absent that you can get wins.
It can come at the cost of runtime performance though, as rust won't (by default) do things like inline across translation units iirc. You can get back some of this perf back via various tricks (for example link-time optimization).
Looks like the rust performance book has some writing on these tradeoffs. I haven't read these articles, but the table of contents on the left seems reasonable enough.
https://nnethercote.github.io/perf-book/build-configuration.html
Again I haven't read that (so I'm assuming it says the following), but you can get "best of both worlds" by configuring debug builds to not do LTO (= faster compilation speed, slower runtime), and release builds to do LTO (= faster runtime, slower compilation speed). There are also variants of LTO that make various tradeoffs you could look into.
That article also links to the `cargo-wizard` subcommand of cargo
https://github.com/Kobzol/cargo-wizard
it won't auto-split crates for you (of…
nindalf · 2024-03-20
> Is it an unpopular opinion to say 75% of “a lot” is still “a lot”
I don’t know if it’s unpopular, but it may be inaccurate. OP claims that they improved by 75%, so you probably meant “25% of a lot is still a lot”.
> I would expect incremental build speedup to be prioritized, and steadily improving. But clearly it isn’t moving very fast in that direction. So why not?
Is this assessment based on something?
For what it’s worth, people have been working on it for years, with varying approaches and levels of success. The recent spate of articles you’ve seen is precisely because these approaches are bearing fruit. Several folks have worked on making a previously single threaded frontend multithreaded, others have added an option to swap the LLVM backend out for a much faster one (cranelift), and yet others are working on moving to a faster linker by default.
The net gain from all of these once they land could be as much as 30–50%, depending on the project, mode of compilation (clean or incremental) and hardware (single/multiple cores). That is a pretty fantastic improvement, considering the whole year improvements in the last 4 years have been 7%, 17%, 13% and 15%, for an overall speed gain of 37%.
If all of this doesn’t sound impressive, I’d encourage you to read nnethercote’s annual reports which explain how much effort went into making compile times faster. 2023’s report - …
nnethercote · 2023-08-26
I've tried AST memory layout work in the Zig style, look for "shrinkage" in these two posts:
- https://nnethercote.github.io/2022/10/27/how-to-speed-up-the-rust-comp…
- https://nnethercote.github.io/2023/03/24/how-to-speed-up-the-rust-comp…
It's hard work. Small AST changes often require hundreds of changes to the code. The required changes usually make the AST less ergonomic to work with. And the perf benefits I obtained were very small. Even after shrinking `ast::Expr` (by far the most common AST node kind) from over 100 bytes to 64 bytes on 64-bit.
The linked Zig PR has very impressive reductions in walltime/cycles/etc. but if you read closely it's restricted just to parsing, which is usually a very small slice of compile time, at least for rustc. My experience with these kinds of changes was disappointing. I concluded "I’d love to be proven wrong, but it doesn’t feel like this work is taking place in a good part of the effort/benefit curve."
Tobu · 2022-02-16
The compiler itself is fine and its performance well managed, with weekly perf triage and efforts driven by profiling[1], but because adding dependencies is effortless and vetting them isn't, dependency trees tend to get large if not careful. In particular, widely used proc-macros (code transformations pulled by popular packages like serde, clap, tokio…) add very heavy dependencies (like syn) to the critical path. As a consequence, downloading and installing a tool from source is often a poor experience.
As far as development experience, cargo clippy / cargo check / rust-analyzer give you the feedback you need without involving codegen (except for any proc-macros in your dependency tree), and incremental compilation makes codegen faster after the first build. Work is also ongoing[2] to make debug-quality codegen faster.
Here is a quality article on the art of keeping a Rust project fast to build:
https://matklad.github.io/2021/09/04/fast-rust-builds.html
The overall series on organizing a large project is worth reading as well:
https://matklad.github.io/2021/09/05/Rust100k.html
[1]: https://nnethercote.github.io/2021/11/12/the-rust-compiler-has-gotten-…
[2]: https://bjorn3.github.io/
Rendello · 2026-07-26
Just don't do it like Rust inlining annotations:
<No annotation> – Gently suggests inlining
#[inline] - Really suggests inlining
#[inline(always)] – Really Really suggests inlining (still not guaranteed!)
https://nnethercote.github.io/perf-book/inlining.html
armchairhacker · 2026-01-25
Machine code and LLVM are complicated messes. Higher-level language hide a lot, but sometimes issues pop up, even in Rust e.g. inline heuristics (https://nnethercote.github.io/perf-book/inlining.html).
vinhnx · 2025-11-24
Print version (full page) https://nnethercote.github.io/perf-book/print.html
epage · 2025-06-27
> Second (and a much worse problem) are macros. They actually hit the same issue. A macro that expands to 10s or 100s of lines can very quickly take your 10000 line project and turn it into a million line behemoth.
Recently, support as added to help people analyze this
See https://nnethercote.github.io/2025/06/26/how-much-code-does-that-proc-…
edward28 · 2025-03-29
link is broken. should be https://nnethercote.github.io/2025/03/19/how-to-speed-up-the-rust-comp…
Yoric · 2024-06-02
Yes, the default implementation of hashing in Rust is designed to be cryptographically-safe at the expense of speed. You can get a large speedup by replacing it, e.g. https://nnethercote.github.io/perf-book/hashing.html .
estebank · 2024-02-28
If you can assure that bounds checks are not necessary (either by construction, because it's a statically sized array, or by runtime check because you do a length check once at runtime), then doing those same things will tell rustc enough to know that bounds checks aren't needed[1][2]. If you think you don't need bounds checks, but can't communicate that in code, such as with an assertion (or if rustc had a bug that misses those checks, unlikely but could happen), then yes, you'll end up with bounds checks unless you use get_unchecked in an unsafe block.
I'm failing to see how this is an onerous difference.
1: https://nnethercote.github.io/perf-book/bounds-checks.html
2: https://github.com/Shnatsel/bounds-check-cookbook/
thraway3837 · 2023-08-25
The author is a member of the Rust team. https://nnethercote.github.io/about-me.html
Their blog posts are also posted multiple times on Hacker News by different identities.
https://news.ycombinator.com/from?site=nnethercote.github.io
Seems odd that this wouldn’t go into an official Rust blog when you’re a member of the team and instead published on your personal domain and blog.
MallocVoidstar · 2023-06-19
Also, codegen-units = 1 disables some compiler parallelization which means it can find more optimizations, including for size: https://nnethercote.github.io/perf-book/build-configuration.html#codeg…
cwaffles · 2023-04-20
There's a good discussion on minimizing heap allocations: https://nnethercote.github.io/perf-book/heap-allocations.html
kibwen · 2023-04-20
Note that nnethercote is probably the world's foremost expert on Rust performance (in addition to being the maintainer of Valgrind). See also his long-running blog series where he discusses his efforts to improve the performance of the Rust compiler itself: https://nnethercote.github.io/2023/03/24/how-to-speed-up-the-rust-comp…
nextaccountic · 2023-04-03
A lot of effort is spent to reduce the size of structs in the Rust compiler
https://nnethercote.github.io/2023/03/24/how-to-speed-up-the-rust-comp…
3% and 6% of improvement doesn't seem like much, but at the level of rustc those big wins
Performance of Rustc must be continously tracked (here https://perf.rust-lang.org/) because if you don't proactively fight against bloat, the tendency is that the code will become slower over time (due to new features etc)
afdbcreid · 2023-02-13
The Rust Performance Book - https://nnethercote.github.io/perf-book/.
arcticbull · 2022-08-08
(5) is pretty irrelevant, ABI isn't language.
You can strap basically any language on top of the C ABI. Many contender languages either use it natively or offer low-cost/no-cost C ABI bindings, specifically as its the lingua franca ABI.
You can check (5) off your list if your choice of replacement language has easy C ABI interop.
[edit]
(1) isn't particularly relevant either. These days the tooling for detecting memory leaks, data races, bugs, etc, operates at the debug info (DAWRF/dSYM) level. It doesn't matter what compiler or input language generated the debugging information, the tools should work just fine. You can run valgrind on your Rust binary for instance. [1] Is there any such tooling that specifically depends on the input source being C? I guess some static analysis tools?
[1] https://nnethercote.github.io/2022/01/05/rust-and-valgrind.html
ninkendo · 2022-08-08
One additional data point: The Rust compiler got ~2% faster when they made some of the core traits in the serializer infallible (ie. panic instead of using Result): https://github.com/rust-lang/rust/pull/93066
Writeup from the contributor: https://nnethercote.github.io/2022/02/25/how-to-speed-up-the-rust-comp…
> The Decoder trait used for metadata decoding was fallible, using Result throughout. But decoding failures should only happen if something highly unexpected happens (e.g. metadata is corrupted) and on failure the calling code would just abort. This PR changed Decoder to be infallible throughout—panicking immediately instead of panicking slightly later—thus avoiding lots of pointless Result propagation, for wins across many benchmarks of up to 2%.
pcwalton · 2022-05-10
FNV is slow because it only goes one byte at a time. An easy improvement for basically no extra complexity is the FxHash, which is popular in Rust for simple non-secure workloads: https://nnethercote.github.io/2021/12/08/a-brutally-effective-hash-fun…
Obligatory disclaimer: Don't use any of this in cryptographic contexts.
Ar-Curunir · 2021-12-31
Contrary to what you say, rust compilation speed is a top priority for rustc developers. Rust compiler times have gone down YoY every year for the past few years. See, eg, https://nnethercote.github.io/2021/11/12/the-rust-compiler-has-gotten-…
howdydoo · 2021-12-08
>Has there been much improvement in compile times in the past ~2 years?
Yes. Source: https://nnethercote.github.io/2021/11/12/the-rust-compiler-has-gotten-…
In my experience, compile times are more a function of project structure than anything else. The compilation unit is a crate, so keep your crates nice and small, and you'll be fine.
SAI_Peregrinus · 2021-04-14
The simplest tool is to just grep for various constructs that copy or allocate. Clippy, the Rust linter, will find some of these (as well as other issues, some of which tend to cause performance problems).
The better tool is to profile the code, then optimize hotspots. There's a Rust Performance Book with a list of profilers known to work with Rust programs[1]. Rustc does support Profile Guided Optimization[2] which is often pretty good at speeding up the output even without any code changes.
[1] https://nnethercote.github.io/perf-book/profiling.html
[2] https://doc.rust-lang.org/rustc/profile-guided-optimization.html
hobofan · 2020-11-17
Pretty good news day for Rust between this, min_const_generics stabilizing[0], and CXX 1.0 (including a nice "book")[1] being released.
EDIT: Oh, and the Rust performance book[2].
[0]: https://github.com/rust-lang/rust/pull/79135
[1]: https://cxx.rs
[2]: https://nnethercote.github.io/perf-book/