I actively avoid Rust projects because they take too long to compile.
I wish rustc had an option for disabling monomorphization, a true -Os option.
I actively avoid Rust projects because they take too long to compile.
I wish rustc had an option for disabling monomorphization, a true -Os option.
> I doubt that a hypothetical version of Rust that avoided monomorphization would compile any faster. I remember doing experiments to that effect in the early days and found that monomorphization wasn't really slower. That's because all the runtime bookkeeping necessary to operate on value types generically adds up to a ton of code that has to be optimized away, and it ends up a wash in the end. As a point of comparison, Swift does all this bookkeeping, and it's not appreciably faster to compile than Rust; Swift goes this route for ABI stability reasons, not for compiler performance.
> What you would need to go faster would be not only a non-monomorphizing compiler but also boxed types. That would be a very different language, one higher-level than even Go (which monomorphizes generics).
Edit: Also kernel compile times are a problem for the elite few, while kernel bugs are a problem for everyone.
If you have to restart an embedded system or schedule a job on a cluster to properly test, that can work out to huge savings.
It would still be nice to see them substantially improve. I know there’s been effort to get debug mode to build substantially faster with cranelift, but I forget if that’s in stable now.
Still, I would say Rust is fast enough now that compile time isn't a show stopper.
A host of other issues, which Rust notably doesn't suffer from, are almost "unfixable", even in the long term: think build system, type system, memory safety. Rust is fine in these regards.
Standard library actually shouldn’t increase compile time at all really, since it’s prebuilt and included for most platforms (excepting -Z build-std).
My hardware is an 11th gen Intel i7 (4-core, 8-thread) laptop. I included time to build but did excluded time to fetch dependencies. I measured real (wall) time and user time with time(1). I compiled clean release builds in both cases (I think). Here's what I found:
uutils/coreutils: I fetched dependencies (`cargo fetch`) ahead of time, then just ran `time cargo build --release` to build everything. This took 1m37s wall time, 4m19s user time. It looked like about half of that time was spent compiling the `coreutils` multicall (Busybox-style) binary itself, after compiling all the individual `uu_*` utilities (`uu_cat`, etc.).
GNU coreutils: I fetched dependencies (`git submodule update --init --recursive`) ahead of time, then read `README-hacking`, which indicates a three-step build process:
time ./bootstrap: 2m42s wall time, 4m32s user time
time ./configure: 0m36s wall time, 0m21s user time
time make -j8: 0m21s wall time, 2m24s user time
I don't know exactly what ./bootstrap is doing? It's a 1500-line shell script. It does seem to download pofiles at the start, so knock 10s off its runtime. A lot of its time seems to be spent in gnulib-tool(1); it runs aclocal(1) and m4(1) near the end, but I didn't notice it running cc(1). (I'm just watching top.) Maybe someone who knows this codebase better can comment how to fairly compare these.So, if we're measuring "time for clean release build on a new dev's machine (not including network fetches)", we're looking at ~200s for GNU coreutils and 97s for uutils/coreutils. If we discount ./bootstrap for whatever reason, that goes down to 57s vs. 97s. Either way, it seems within a factor of roughly 2, with the winner going one way or another depending on how you count.
Methodology comments welcome.
Using a different linker (like mold) might change that, if most of the time is spent linking everything together.
$ readelf -p .comment ./target/release/coreutils
String dump of section '.comment':
[ 0] rustc version 1.74.0 (79e9716c9 2023-11-13)
[ 2c] GCC: (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
[ 57] mold 2.3.3 (49066ea329979c3187556091ba62421594799fd1; compatible with GNU ld)
[ a6] GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
I may have done something wrong; let me know if you get substantially different results.(Edited for new timings with mold 2.3.3 instead of 1.0.3.)
Can this power be learned?