Live data from Hacker News

Thoughts on Rust bloat

raphlinus.github.io

21–30 of 313 posts

Re: Thoughts on Rust bloat

#21
post #12

It looks like the author is most bothered by compile times of dependencies. Cargo needs to do better with shared caches (so you compile each dep at most once per machine) or ability to get precompiled crates (so you don't even compile it). Incremental improvements of compiler speed or trimming of individual dependencies won't bring the 10x improvement it needs.

One of the biggest issues that I face with Rust is that its builds are enormous, and I often work on machines with limited disc space.

The actual binary sizes are fine - even with embedded devices that have I really appreciate Rust's inclusive approach to learning and teaching, but I can't justify using it for education on ultra-affordable machines for that reason. People often scatter one-off projects all over the place as they learn, and when they run out of space it takes a long time to clean everything up.

So I would also be very in favor of some sort of simple shared package cache.

Re: Thoughts on Rust bloat

#22
post #6

Use polymorphism sparingly I think it is a little ironic that he speaks of performance culture but simutaneously advises to use dynamic dispatch and avoid polymorphism. I can see the justification in non-critical code paths, but serialisation is a pretty important part of most networked software nowadays so I do not think that smaller binaries and faster compilation times (better developer experience) justifies a per…

Performance culture has you measure the actual performance implications, then make an informed decision. Is the code on a performance-critical path? Maybe some of your serialization code is, but it's extremely unlikely that a dynamic dispatch when parsing command line args is the reason your app is slow. Also be aware that highly inlined code does nicely in microbenchmarks but might have significantly negative perfor…

I do agree with you with the measuring aspect. Part of building high-performance systems is being able to measure performance in an accurate and actionable way, and consequently optimise code paths that have significant performance impacts.

However, I do believe that a competent engineer would have the judgement to be able to see, roughly, where performance hits would likely arise and optimise accordingly. Command-line arguments would likely not fall under this mandate, but serialisation to stdout is likely a good candidate for well-designed and well-optimised code. A nice side-effect is that this also avoids significant refactors down the line when you need to, in this case, change your serialisation from dynamic dispatch to static dispatch.

Re: Thoughts on Rust bloat

#23
post #8
post #7

Rust bloat is a serious issue that is not being taken seriously I think. I raised the issue about platform size in June: https://github.com/rust-lang/rust/issues/61978 and its actually gotten worse since then, significantly worse. In the 2 months since then the installer has increased from 203 MB to 299 MB. Also unbelieveably, Rust has failed to address package balkanization which I would say has ruined the Node comm…

Also unbelieveably, Rust has failed to address package balkanization which I would say has ruined the Node community. I'd say that this is more of a culture thing rather than a language thing.

Whether culture or language, if it is not addressed then expect similar results :(

Re: Thoughts on Rust bloat

#24
post #6

Use polymorphism sparingly I think it is a little ironic that he speaks of performance culture but simutaneously advises to use dynamic dispatch and avoid polymorphism. I can see the justification in non-critical code paths, but serialisation is a pretty important part of most networked software nowadays so I do not think that smaller binaries and faster compilation times (better developer experience) justifies a per…

Performance culture has you measure the actual performance implications, then make an informed decision. Is the code on a performance-critical path? Maybe some of your serialization code is, but it's extremely unlikely that a dynamic dispatch when parsing command line args is the reason your app is slow. Also be aware that highly inlined code does nicely in microbenchmarks but might have significantly negative perfor…

> Also be aware that highly inlined code does nicely in microbenchmarks but might have significantly negative performance implications in a larger system when it blows out the I-cache.

I see this assertion a lot, but I have never actually seen a system in which inlining that would otherwise be a win in terms of performance becomes a loss in a large system. LLVM developers seem to agree, because LLVM is quite aggressive in inlining (the joke is that LLVM's inlining heuristic is "yes").

I'd be curious to see any examples of I$ effects from the effects of inlining specifically in large systems mattering in practice.

Re: Thoughts on Rust bloat

#25
post #7

Rust bloat is a serious issue that is not being taken seriously I think. I raised the issue about platform size in June: https://github.com/rust-lang/rust/issues/61978 and its actually gotten worse since then, significantly worse. In the 2 months since then the installer has increased from 203 MB to 299 MB. Also unbelieveably, Rust has failed to address package balkanization which I would say has ruined the Node comm…

> package balkanization

Balkanize definition: to break up (a region, a group, etc.) into smaller and often hostile or uncooperative units.

Are you implying there are competing crates with belligerent attitudes to each other?

> which I would say has ruined the Node community

I thought it was the basis and strength of node... (However I am too scared to use node or node toolchains: I fear trojans since I don't trust all dependencies).

Re: Thoughts on Rust bloat

#26
post #2

It's a little unfortunate that some of the cool features of Rust need to be put into the "use sparingly" category. I know that polymorphism, async, etc. should be used judiciously anyway, but still. One recent case we saw a similar tradeoff was the observation that the unicase dep adds 50k to the binary size for pulldown-cmark. In this case, the CommonMark spec demands Unicode case-folding, and without that, it’s no…

  > In the Python world, you can install an "extra" along with a    package. So you can make the deliberate decision to omit Unicode case folding from your CommonMark parser. Maybe something like that is possible with a crate?
This is definitely possible in Rust with Cargo crate features! [0]

For instance in a game library like quicksilver you can opt in to WebAssembly support, images, fonts, audio handling, etc. Then the image or audio library themselves can put formats and codecs behind feature flags for instance. Each crate then uses conditional compilation to branch out these features at compilation time. More commonly as an end-user, test modules use a special conditional compilation macro [1].

[0] https://doc.rust-lang.org/cargo/reference/manifest.html#the-... [1] https://doc.rust-lang.org/stable/rust-by-example/testing/uni...

Re: Thoughts on Rust bloat

#27

Earlier quoted context omitted.

Performance culture has you measure the actual performance implications, then make an informed decision. Is the code on a performance-critical path? Maybe some of your serialization code is, but it's extremely unlikely that a dynamic dispatch when parsing command line args is the reason your app is slow. Also be aware that highly inlined code does nicely in microbenchmarks but might have significantly negative perfor…

> Also be aware that highly inlined code does nicely in microbenchmarks but might have significantly negative performance implications in a larger system when it blows out the I-cache. I see this assertion a lot, but I have never actually seen a system in which inlining that would otherwise be a win in terms of performance becomes a loss in a large system. LLVM developers seem to agree, because LLVM is quite aggressi…

One somewhat related example I can think of was how the v8 javascript implementation switched from a baseline compiler to a baseline interpreter. The interpreter version has less startup latency (because compiling to bytecode is less work) and uses less RAM (because bytecodes are more compact).

It isn't exactly about inling but it is an example where optimizing for size also optimized for speed at the same time.

Re: Thoughts on Rust bloat

#28
post #12

It looks like the author is most bothered by compile times of dependencies. Cargo needs to do better with shared caches (so you compile each dep at most once per machine) or ability to get precompiled crates (so you don't even compile it). Incremental improvements of compiler speed or trimming of individual dependencies won't bring the 10x improvement it needs.

Can you not do this by setting CARGO_TARGET_DIR to something universal? Maybe there is a downside here that I haven't considered.

Re: Thoughts on Rust bloat

#29
> There’s also an effort to analyze binary sizes more systematically. I applaud such efforts and would love it if they were even more visible. Ideally, crates.io would include some kind of bloat report along with its other metadata, [...]

This is what I always wanted (for Rust as well as for C) but never got around to hack together myself. I dreamt it up more as a feature of cargo though, something like 'cargo stats' or so. Shouldn't be to hard and cargo is extensible.

Re: Thoughts on Rust bloat

#30
post #8

Earlier quoted context omitted.

Also unbelieveably, Rust has failed to address package balkanization which I would say has ruined the Node community. I'd say that this is more of a culture thing rather than a language thing.

Whether culture or language, if it is not addressed then expect similar results :(

The primary way I can see to address this is to make packaging more difficult. Are there other steps that a language can take to avoid this problem?
Post reply on HN