Hacker News new | ask | show | jobs
by yogthos 23 days ago
I find the real issue with Rust is the compiler performance. I decided to use it for a project, and frankly I have huge regrets now that it's grown big enough. It literally takes over a minute to compile on my M1 laptop.

I just don't understand how people find this sort of thing normal. If you implement a feature, and then you want to see it in action, the feedback loop for that is insanely slow. It's incredibly jarring coming from Clojure where you have a live development experience.

I've used Go before, and while you still have to wait for compiling, at least the compiler is actually fast.

I get the problem Rust aims to solve, but the ergonomics are just not there in my opinion.

5 comments

There are a number of compiler performance enhancements (and correctness improvements) that are being worked on that are kind of at a chokepoint behind some other piece of work. Unfortunately it's not that easy to discern what state they're in or how quickly they're making progress.

At some point though a lot of work will be able to start advancing at once, so long as people exist to do the work.

e.g. https://rust-lang.github.io/rust-project-goals/2026/parallel...

I had similar problems. Compilation got 10x faster once I split one crate into workspace with crates inside. The checks are only done on the compiled one. Then, I got rid of serde, because its derive macros are heavy and add some seconds of hickup (other serialization frameworks based on proc macros are slow too: rkyv, musli).
See languages like D, Delphi, Ada, C++ (with modules/libraries, REPLs like CINT), Haskell (GHCi), OCaml (REPL) for similar complexity levels, and faster compile times.

It is a matter of tooling, eventually they will get there I guess.

There's a tooling problem in the compiler with regards to parallelism, but the real problem is that the Rust ecosystem makes use of intense amounts of code generation features, like serdes, which generates a huge amount of invisible code so that you can serialize and deserialize JSON at speeds that may or may not be practically relevant, but whose impact on compile times is guaranteed.
The relevant part is without proper way to cache it, so rebuilding everything requires lots of external stuff that every single developer has to manually configure.

However as language nerd, I still think there is a possible way out of it.

Have you switched to a faster linker [0] yet? Do you use sccache?

[0] https://github.com/rui314/mold

oh didn't know about this one, will have to try
Yeah rust has issues. Have you tried splitting your project into multiple crates if possible?
I haven't tried that yet, I guess that would be an option once I get a few stable pieces that I'm not likely to be touching much.
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....

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 course), but it does seem to give you some default configurations of `cargo`, one of which configures for faster compilation speed. could be an easy way to mess around with things.

Thanks, that's helpful to keep in mind. Looks like you can fiddle with organizing the project in way where you can balance 1 and 2 in a reasonable way. Right now, it's definitely the second step that's killing me where assembling the crates together takes forever.
you can try doing `cargo build --timings ...`. It will generate a report of how long each crate takes to compile etc. It sounds like you know that your final crate is the culprit, but this would let you confirm it.

If you suspect the issue is assembling all the files together (e.g. linking) you can see some advice on optimizing link speeds here

https://nnethercote.github.io/perf-book/build-configuration....

Note that there could be other causes of slow compilation of the final binary. For example, if you heavily use (especially procedural) macros, it's known to make compilation quite slow.