anaqin
4 days ago
Good write up! I was hoping it was going to conclude with the author getting buns zig build way faster than Rusts but a good deep dive nevertheless
lalitmaganti
4 days ago
Having spent ~3 weeks of evenings and weekends on this, I was a bit burned out to keep trying to optimize especially because all of this code is just a dead end anyway...
The fix seemed to be to split up Bun's Zig module into ~100 pieces just like they've done on Rust but how representative that would have been on anything Bun might of shipped is very much in question!
pfg_
4 days ago
The issue with splitting up Bun's Zig module is that Rust is designed for multiple crates compiling separate objects and linking them together in the end, but for Zig you would need to manually export and import C abi functions and you can't make use of language features like slices, generics, non-extern structs, and others anymore. In Zig, every module is compiled in the same compilation unit. Even the standard library is compiled in the same unit as your app.
hbbio
3 days ago
Zig 0.17 should solve this with incremental compilation. What you said will stay but should only apply for the first compilation.
anaqin
4 days ago
Your post went into way more depth than I was expecting when I first opened up it up. You clearly spent a lot of time on it and I appreciated reading the tale so thank you. Given all the drama around AK / Bun, it just would have been so funny to see someone not involved in the project solve one of the main motivations for the move to rust.
I believe there is a fork of bun from 1.3 that a different community is maintaining. I wonder if they’ve been able to get the compile times down by modularizing the build?
listic
4 days ago
> I believe there is a fork of bun from 1.3 that a different community is maintaining.
There is Buz effort to do this which might be worked at, behind the scenes: https://github.com/jazzzooo/buz
(I'm looking forward to looking into Zig)
bloaf
4 days ago
The next questions in my head are:
A) Is there any performance penalty on the compiled result due to being optimized in separate pieces
B) If not, why isn't the optimizer smart enough to split them up internally and optimize in parallel?
lalitmaganti
4 days ago
> A) Is there any performance penalty on the compiled result due to being optimized in separate pieces
AFAIK, the answer to this is no but only if LTO is doing a good job and actually optimizing well across object files.
> B) If not, why isn't the optimizer smart enough to split them up internally and optimize in parallel?
I think there was another comment by someone more knowledgable in Zig that this is something which is being discussed by the Zig compiler team.
rahkiin
4 days ago
Can you force a non-parallel build of those rust crates to make the comparison fairer?
lalitmaganti
4 days ago
Nice idea! I was only thinking about "how could I make Zig more efficient", I didn't even consider making Rust more similar to Zig.
I added a Python script wrapping rustc which serializes all rustc invocations for bun_* crates; you can find the recoridng at [1]. Turns out it only increased the build by 1 minute! So clearly my intuitition that it was just crate parallelism was not correct.
One more confounding factor though is that rustc is parallelised while Zig's compiler is not (yet). So it's still possible that might be the reason.
[1] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
epage
2 days ago
Why not just pass `-jobs 1` to cargo?
Still won't be quite apples to apples because a multi-crate project will serialize more to disk.
lalitmaganti
a day ago
Because that would also cause the dependencies to be compiled in series also! The point was only to measure "what if the Bun crate was built in one shot" not any dependencies of Bun.
Retro_Dev
4 days ago
this! - the reason Zig defaults to one semantic analysis thread is due to current (to be improved) limitations; some ideas for Zig also will require one compilation unit - the restricted function pointers proposal being a good example: https://github.com/ziglang/zig/issues/23367
The bun team tried to parallelize Zig's semantic analysis a while back - and it DID compile about 4x as fast... YET the builds were no longer deterministic, which is a hard requirement for lots of things. More effort will need to be spent here than naively adding a thread pool. Hopefully Zig's Sema.zig gets faster, but Rust is also super slow at compiling and needs to improve. Oh - one last thing to note, Zig has very fast debug compilation and incremental compilation, it's a real nice thing to work with that you simply can't approach in most other languages right now.
lalitmaganti
4 days ago
> The bun team tried to parallelize Zig's semantic analysis a while back - and it DID compile about 4x as fast...
I actually collected a build with multi-threading turned on [1]. It helped quite a bit, cutting the Zig object time from 7m49s to 4m05s. But because of the reason you mentioned (and the post was already so long!) I decided not to bring it up.
> Oh - one last thing to note, Zig has very fast debug compilation and incremental compilation, it's a real nice thing to work with that you simply can't approach in most other languages right now.
Yes, in fact I also tested just running bun run build / bun run build:release and captured traces for both! The clean release build took 3m36s for Zig versus 5m50s for Rust [2][3]. Clean debug was closer: 3m07s versus 3m27s [4][5].
I also tried incremental debug builds: adding a comment to output.zig / output.rs took 48.6s / 65.4s to rebuild. Ordinary developer builds certainly gave a different picture from CI.
[1] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
[2] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
[3] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
[4] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
[5] https://buildprof.lalitm.com/#!/?url=https%3A%2F%2Fblogexamp...
saghm
3 days ago
"Fairer" seems like a strange characterization if what you're actually telling to measure is real-world compile times. If two people were running a race and one had better, trying to make the race "fairer" by forcing that one to run with the same form as the other pretty silly.