Comment by nu11ptr
3 days ago
This is interesting. It got me to think. I like it when articles provoke me to think a bit more on a subject.
I have found this true for myself as well. I changed back over to Go from Rust mostly for the iteration speed benefits. I would replace "fast" with "quick", however. It isn't so much I think about raw throughput as much as "perceived speed". That is why things like input latency matter in editors, etc. If something "feels fast" (ie Go compiles), we often don't even feel the need to measure. Likewise, when things "feel slow" (ie Java startup), we just don't enjoy using them, even if in some ways they actually are fast (like Java throughput).
I feel the same way about Go vs Rust. Compilation speed matters. Also, Rust projects resemble JavaScript projects in that they pull in a million deps. Go projects tend to be much less dependency happy.
One of the Rust ecosystem's biggest mistakes, in my opinion, was not establishing a fiercely defensive mindset around dependency-bloat and compilation speed.
As much as Rust's strongest defenders like to claim, compilation speed and bloat just really wasn't a goal. That's cascaded down into most of the ecosystem's most used dependencies, and so most Rust ecosystem projects just adopt the mindset of "just use the dependency". It's quite difficult to build a substantial project without pulling in 100s of dependencies.
I went on a lengthy journey of building my own game engine tools to avoid bloat, but it's tremendously time consuming. I reinvented the Mac / Windows / Web bindings by manually extracting auto-generated bindings instead of using crates that had thousands of them, significantly cutting compile time. For things like derive macros and serialization I avoided using crates like Serde that have a massive parser library included and emit lots of code. For web bindings I sorted out simpler ways of interacting with Javascript that didn't require a heavier build step and separate build tool. That's just the tip of the iceberg I can remember off the top of my head.
In the end I had a little engine that could do 3D scenes, relatively complex games, and decent GPU driven UI across Mac, Windows, and Web that built in a fraction of the time of other Rust game engines. I used it to build a bunch of small game jam entries and some web demos. A clean release build on the engine on my older laptop was about 3-4 seconds, vastly faster than most Rust projects.
The problem is that it was just a losing battle. If I wanted Linux support or to use pretty much any other crate in the Rust ecosystem, I'd have to pull in dependencies that alone would multiple the compile time.
In some ways that's an OK tradeoff for an ecosystem to make, but compile times do impede iteration loops and they do tend to reflect complexity. The more stuff you're building on top of the greater the chances are that bugs are hard to pin down, that maintainers will burn out and move on, or that you can't reasonably understand your stack deeply.
Looking completely past the languages themselves I think Zig may accrue advantages simply because its initial author so zealously defined a culture that cares about driving down compile times, and in turn complexity. Pardon the rant!
It's fascinating to me how the values and priorities of a project's leaders affect the community and its dominant narrative. I always wondered how it was possible for so many people in the Rust community to share such a strong view on soundness, undefined behavior, thread safety etc. I think it's because people driving the project were actively shaping the culture.
Meanwhile, compiler performance just didn't have a strong advocate with the right vision of what could be done. At least that's my read on the situation.
2 replies →
And that leads to dependency hell once you realize that those dependencies all need different versions of the same crate. Most of the time this "just works" (at the cost of more dependencies, longer compile time, bigger binary)... until it doesn't then it can be tough to figure out.
In general, I like cargo a lot better than the Go tooling, but I do wish the Rust stdlib was a bit more "batteries included".
I feel like Rust could have added commonly used stuff as extensions and provided separate builds that have them baked in for those that want to avoid dependency hell while still providing the standard builds like they currently do. Sure the versions would diverge somewhat but not sure how big of a problem that would be.
This is all well and good that we developers have opinions on whether Go compiles faster than Rust or whatever, but the real question is: which is faster for your users?
...and that sounds nice to me as well, but if I never get far enough to give it to my users then what good is fast binaries? (implying that I quit, not that Rust can't deliver). The holy grail would be to have both. Go is generally 'fast enough', but I wish the language was a bit more expressive.