4 ms·
One thing that's always concerned me about Rust is that everyone mononorphizes everything (e.g. closures are always unboxed except in the rare cases where dynam
by glittery 8y ago
One thing that's always concerned me about Rust is that everyone mononorphizes everything (e.g. closures are always unboxed except in the rare cases where dynamic dispatch is necessary). Hopefully this is a baseless fear, but isn't this a recipe for executable bloat?
- chc4 8y agoYes, and there have been some cases of people hitting very large binaries and having to put effort into slimming them down. In most of those cases it's due to either wanting to run in very constrained space or distribution size, and then the problem is due to some blanket impl for a bunch of types that can safely be removed though. There are a few cargo submodules that will do executable size analysis with regard to monomorphization to show the outliers. There's not really a good solution for this. Having your code be fast by default in exchange for more space seems like the trivially correct choice to make when most people have hundreds of gigabytes of free hard drive space and binaries don't get above a few megas, while CPU speed has stagnated. If they want runtime type matching instead, they can still do it.
- jandrese 8y agoVery large binaries can be a performance problem too if their access patterns end up trashing the cache. Memory access is a common bottleneck on modern CPUs. It depends how big "big" is in this case, and how much of it actually gets executed repeatedly.
- withoutboats 8y agoIt can be! And arguably people have leaned too hard on the decisions made in the std as an example: in std, everything is generic so that it can be inlined well, because std APIs underlie everything. At the application layer, this is not obviously what you want. However, in many cases, a well designed generic API will be able take a trait object in the place of `T`. That way, at the application layer, you can decide to pass trait objects around, reducing code size and - maybe more importantly to you - compile times. cargo does this for example in some places where the performance regression is insignificant but it saves noticeable compile time. Sometimes libraries accidentally don't set things up so that you can pass either a concrete `T` or a dynamically dispatched trait object to their APIs; we're hoping to find a way of making it less likely for this to go wrong in the future.
- nicoburns 8y agoSomething I've been thinking about a lot recently: would there be scope for a compiler mode which used virtual dispatch for generics (as well as trait objects) so as to speed up compile times? (and then you could compile the same code monomorphised for production).
- bbatha 8y agoIt's been proposed before: https://internals.rust-lang.org/t/idea-polymorphic-baseline-codegen/8313 https://internals.rust-lang.org/t/idea-polymorphic-baseline-... Its also fairly common to have code like: fn do_it(a: impl AsRef<i32>) { let a = a.as_ref(); // do something with a } That could be instead monomorphised to be fn _do_it(a: &i32) { // do something with a } fn do_it(a: impl AsRef<i32>) { let a = a.as_ref(); _do_it(a) } saving the inlining of _do_it's code bloat/generation penalty.
- nicoburns 8y agoHmm, interesting the Niko thinks that MIR optimisation passes and CraneLift are more likely to happen soon. I so dearly want faster Rust compile times!
- shawn 8y agoIs executable bloat worth worrying about?
- MrBuddyCasino 8y agoIt is in embedded, and Rust should be suitable for that. Having only 64k of flash is not unusual.
- steveklabnik 8y agoIn those cases, you generally don’t have the standard library, and packages made for these cases tend to care more about binary size.
- RaleyField 8y agoMonomorphization is a feature of compiler not the language, in the context of systems programming binary size often isn't the foremost priority. Perhaps Rust compiler could get feature flag for controlling optimization priorities as I suspect in webasm world one would more often prefer more reasonable network transfer sizes than the fastest running version that is possible.
- Ier6yoCh 8y agoDosn't LLVM have some optimization that can cut down duplicate code blocks created by monomorphization?