Description
This
// empty.rs
fn main() -> ! {
loop {}
}
generates a .text section of 94 bytes
This
// print-no-fmt.rs
fn main() -> ! {
iprintln!("The answer is ");
loop {}
}
generates a .text section of 314 bytes
But this
// print-with-fmt.rs
fn main() -> ! {
iprintln!("The answer is {}", 42u8);
loop {}
}
generates a .text section of 2340 (!) bytes
Everything (including core
) was compiled with opt-level=3 + LTO + panic=abort. FWIW, opt-levels s
and z
make little difference.
The question is: Can we improve binary sizes? (and run time?)
Steps To Reproduce
$ git clone --depth 1 https://github.com/japaric/f3
$ cd f3
$ xargo build --target thumbv7em-none-eabihf --no-default-features --example minimal --release
Then tweak examples/minimal.rs
accordingly.
Observations
-
Looking at the disassembly of
print-with-fmt.rs
. It seems that the compiler is not inlining anything insidecore::fmt
. The probable cause is that thefmt::Write
trait makes use of trait objects in its implementation.
Possible solutions
-
Reduce the number of
panic!
s andunwrap
s in thecore::fmt
implementation. -
Create an alternative
core::fmt
implementation that uses generics instead of trait objects to incentivize inlining and better optimizations. -
Create an alternative
core::fmt
implementation that provides less formatting options.
The last two solutions will require a new fmt::Write
trait.
Meta
$ git rev-parse HEAD
2d28ca4e59f5971113d07992968bc9230357d08c
$ rustc -V
rustc 1.14.0-nightly (5665bdf3e 2016-11-02)
$ xargo -V
xargo 0.2.1 (700605d 2016-11-01)
cargo 0.13.0-nightly (717adc8 2016-11-02)
Tagging with the community
label as this may require an out of tree re-implementation of the fmt::Write
trait that could end up living in crates.io.