5 ms·
Rust adopted Node's quadratic dependency model, so Rust binaries are going to be O(n^2) larger and tree shaking isn't going to help unfortunately.
by jart 4y ago
Rust adopted Node's quadratic dependency model, so Rust binaries are going to be O(n^2) larger and tree shaking isn't going to help unfortunately.
- pdimitar 4y agoWhy wouldn't it help? Surely this (and others) method do static analysis on what's actually used in the final program, no? 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.
- jart 4y agoWell it helps, but it'd be like spooning water out of a bucket when a faucet is pouring more into it. The NPM dependency model solves the diamond dependency problem by schlepping in multiple versions of the same package. C / C++ / Java (and I assume Zig too) require a single version of any given package. The way Rust and NPM do things adds a whole dimension of complexity to what needs to be shaken. It's sort of like a devil's bargain because it helps their ecosystems grow really fast, but it creates a lot of bloat over the long run. Rust is still relatively new so binary sizes are still pretty good compared to what we might witness in the future. So enjoy the golden age of Rust while it's golden!
- metaltyphoon 4y agoDoes that also apply for Go?
- jart 4y agoNo I don't think so, but I'm not certain. I think with Go the problem always had more to do with the way the language is designed, making it difficult for the linker to prune dependencies.
- sideeffffect 4y agoWow, really? I've always thought that Cargo by default forces a package into one particular version. And that a particular package in multiple versions is something people opt into only in rare circumstances (similarly as in Java/Maven/shadowing case). I'm no Rust expert though.
- steveklabnik 4y agoCargo attempts to unify versions where possible, but if the versions are incompatible, will choose multiple ones. 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.
- dietr1ch 4y agoThis doesn't sound too bad, and functions* that are not changing could, in theory, also be unified, although a single change in one of the transitive functions called might force you to keep multiple versions.
- jart 4y agoIt's bad enough to make packages quadratic.
- dietr1ch 4y agoI'm not really familiar with packaging problems and obviously quadratic is worse than linear, but is having no duplicates a real alternative? (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.