Example: you use a crate with 13 functions. You only use 1 but it depends on 2 others in the same crate that don't depend on anything else. Why shouldn't the end result only compile 3 of the 13 functions?
Or maybe I am misunderstanding or I am badly informed (not a compiler / linker engineer so I'm likely with naive assumptions) -- apologies if so.
I understand it's not easy, I am just a bit surprised that Rust's team is not chasing this a bit more aggressively, let's say. It puts a slight stain on an otherwise excellent project.
I'm no Rust expert though.
If your deps ask for 1.2.3, 1.2.4, and 2.0.0, your binary will include the necessary functions from 1.2.4 and 2.0.0.
I still wish at one point binary sizes are taken seriously though. But I am aware that it's likely (a) not at all a priority currently, and (b) a gigantic effort.
Guess I'll dig out the guides for reducing binary sizes but last time I needed tokio + opentelemetry + a Prometheus adapter my release binary was always at least 5MB.
Also sorry, didn't mean to come off as dismissive. It's just that to me 5MB is quite a lot and should be shrinkable. I keep wondering if the compiler/linker tech can help Rust there.
Having said that, if your binary ended up including a hyper-based HTTP server and a TLS implementation, and was built with the default release profile (optimizing for speed rather than size), I can believe it would reach 5MB stripped.
Debug symbols stripped it clocks at 5.9M, all symbols stripped it's at 5.0M.
Obviously this is not critical. But I have to admit I envy Zig and OCaml. :)
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = "z"
panic = "abort"
Take out that last line if you need to recover from panics at runtime. So far, in my limited use of Rust, I haven't had to. Anyway, those are all the easy tweaks to reduce binary size.From 5.0M to 3.0M, not bad!
Turned the optimization for speed back on -- 4.4M! Wow.
(Disclaimer: I'm mostly guessing here, but am I missing something important?)
AFAIU the choice here also considers how easily things will build and link, and whether your package manager/build tool will need a SAT-solver to figure out which version of each library to use, and even then you can still run into unsatisfiable restrictions (`Could not resolve dependencies`) if libraries are not adequately updated/maintained.
It seems that by allowing duplication "only" pay for the libraries that are not updated (including all their deps), which means that you are trading computer resources (disk, cpu?) for human time updating and debugging, which might be a really good deal, especially if you only end up with duplicates in the cases where you lack the human time to keep all deps updated.
One could argue that the time cost of maintaining the libraries can only be deferred so there's no benefit deferring it, but the time people using the libraries save because they don't need the libraries to get updated if they have enough disk is probably what made Rust and NPM just duplicate dependencies.