← Back to context

Comment by api

6 months ago

Speaking of bloat: why are binaries from Rust or (much worse) Go so damn huge? This is in release mode with debug off.

It’s weird because memory use for the same sorts of programs is not much worse than other languages. In Rust memory use seems comparable to C++. In Go there’s a bit more overhead but it’s still smaller than the binary. So all this is not being loaded.

I get the sense devs just don’t put a lot of effort into stripping dead code and data since “storage is cheap” but it shows next to C or even C++ programs that are a fraction of the size.

I see nothing about Rust’s safety or type system that should result in chonky binaries. All that gets turned into LLVM IR just like C or C++.

Go ships a runtime so that explains some, but not all, of its bloat.

Mostly because of static linking. C and C++ don't put every library they need in the binary by default. The advantage is that a pure Go or Rust binary just works (most of the time) when copied from one machine to another, you don't have to care about installing other libraries.

  • That’s a great point.

    Another advantage is that at least for Rust you can do whole program optimization. The entire program tree is run through the optimizer resulting in all kinds of optimizations that are otherwise impossible.

    The only other kinds of systems that can optimize this way are higher level JIT runtimes like the JVM and CLR. These can treat all code in the VM as a unit and optimize across everything.

    •   C++ has had whole program optimization since forever. And you can use static linking if you want, the same as Rust.

    • > Another advantage is that at least for Rust you can do whole program optimization. The entire program tree is run through the optimizer resulting in all kinds of optimizations that are otherwise impossible.

      I get why this might lead to big intermediate files, but why do the final binaries get so big?

      2 replies →

  • Go especially, on some platforms they go straight to syscalls and bypass libc entirely. They even bring their own network stack. It's the maximalist plan 9 philosophy in action.

    • I don't really like Go as a language, but this decision to skip libc and go directly with syscalls is genius. I wish Rust could do the same. More languages should skip libc. Glibc is the main reason Linux software is binary non-portable between distros (of course not the only reason, but most of the problems come from glibc).

      11 replies →

Rust doesn’t strip debug info by default.

  • The vast amount of debug info does make the problem worse, but it doesn't take long before a moderately complex Rust programs grows to 100MB even after stripping.

    When I tried to compare Rust programs to their C(++) equivalents by adding the sizes of linked libraries recursively (at least on Linux, that's impossible for Windows), I still found Rust programs to have a rather large footprint. Especially considering Rust still links to glibc which is a significant chunk of any other program as well.

    I believe many of Rust's statically linked libraries do more than their equivalents in other languages, so I think some more optimisation in stripping unused code paths could significantly reduce the size of some Rust applications.