Cornelius Roemer
Cornelius Roemer

Reputation: 8228

Does unreachable Rust code get compiled and included in the final binary?

I'm new to Rust and compiled languages in general. Does every crate I include as a dependency end up in the binary, even if I don't use a single function from that crate?

And if I use just a single function from a big library. Does the entire library get compiled or only that function and whatever that function requires?

In Javascript, there is tree shaking, to eliminate dead code without having any downside other than extra time to shake the tree. Does an equivalent exist for Rust? After all, Clippy is good at finding dead code, so it should be able to just not compile and include in the binary.

I know that it's possible to optimize for binary size using opt = 'z', but that comes at the cost of slower execution.

Upvotes: 0

Views: 593

Answers (1)

Marcus Dunn
Marcus Dunn

Reputation: 580

After a quick look rustc does do some forms of dead code elimination at the IR level.

but I imagine most of the mileage will be from LLVM.

Finally the linker (provided you have lto on) will also remove code it finds is dead.

Importantly, you do not get any guarantees from either rust or LLVM about weather a given dead chunk of code will or will not be eliminated. Trivial cases such as an uncalled function will likely be removed even in debug builds. Keep in mind there is a lot of inlining and transformation done at higher optimization levels so what may not look dead in the source code may eventually turn out to be dead in the final build and removed. If you are really struggling for binary size wondering about if something is removed or not is a inefficient way to go about it. The following link is a great resources and mentions the trade-offs you are making to obtain smaller binaries.

https://github.com/johnthagen/min-sized-rust

highlights from here include:

[profile.release]
strip = true
opt-level = "z"
lto = true
codegen-units = 1

These all have costs (they are not default for a reason!) and I would measure the compilation time, binary size, and hopefully some profiling before and after applying each one to see if the trade off is worth it. The link goes into some behaviour changing ones as well such as panic = "abort".

Of course cargo-bloat cannot go unmentioned - it will help find the problems you mention such as having a library that you use a single function from bringing in a massive amount of code.

Upvotes: 1

Related Questions