rust-lang/rust — pull request #16662 by pczarn (2014-08-21 23:36:43+00:00)
Title: Reduce fmt's rodata usage by unzipping String and Argument arrays

Based on an observation that strings and arguments are always interleaved, thanks to #15832. Additionally optimize invocations where formatting parameters are unspecified for all arguments, e.g. `"{}{:?}{:x}"`, by emptying the `__STATIC_FMTARGS` array. Next, `Arguments::new` replaces an empty slice with `None` so that passing empty `__STATIC_FMTARGS` generates less machine code when `Arguments::new` is inlined.

All in all, this adds a single mov instruction per `write!` in most cases. That's why code size has increased.

Expansion of old `println!`:

```rust
fn main() {
let x = 5i;
match (&x,) {
(__arg0,) => {
static __STATIC_FMTSTR: [Piece, ..] = [
String("x is: "),
Argument(Argument {
position: ArgumentNext,
format: FormatSpec {
fill: ' ',
align: AlignUnknown,
flags: 0u,
precision: CountImplied,
width: CountImplied,
},
},
String(" foobar"),
];
let __args_vec = &[argument(secret_string, __arg0)];
let __args = unsafe { Arguments::new(__STATIC_FMTSTR, __args_vec) };

println_args(&__args)
}
};
}
```

With this PR this becomes:

```rust
fn main() {
let x = 5i;
match (&x,) {
(__arg0,) => {
static __STATIC_FMTSTR: [&'static str, ..2u] = [
"x is: ",
" foobar"
];
static __STATIC_FMTARGS: [rt::Argument<'static>, ..0u] = [];
let __args_vec = &[argument(secret_show, __arg0)];
let __args = unsafe {
Arguments::new(__STATIC_FMTSTR, __STATIC_FMTARGS, __args_vec)
};
println_args(&__args)
}
};
}
```

```
before
text data bss dec filename
15017 43168 8 58193 x86_64-unknown-linux-gnu/stage3/lib/libarena-4e7c5e5c.so
66210 71260 4 137474 x86_64-unknown-linux-gnu/stage3/lib/libdebug-4e7c5e5c.so
31659 3754 4 35417 x86_64-unknown-linux-gnu/stage3/lib/libflate-4e7c5e5c.so
20138 45502 8 65648 x86_64-unknown-linux-gnu/stage3/lib/libfmt_macros-4e7c5e5c.so
76981 83547 4 160532 x86_64-unknown-linux-gnu/stage3/lib/libgetopts-4e7c5e5c.so
10269 44437 8 54714 x86_64-unknown-linux-gnu/stage3/lib/libgraphviz-4e7c5e5c.so
33546 40371 200 74117 x86_64-unknown-linux-gnu/stage3/lib/liblog-4e7c5e5c.so
341427 166384 24 507835 x86_64-unknown-linux-gnu/stage3/lib/libnative-4e7c5e5c.so
47783 207122 4 254909 x86_64-unknown-linux-gnu/stage3/lib/librbml-4e7c5e5c.so
13324534 6303187 368 19628089 x86_64-unknown-linux-gnu/stage3/lib/librustc-4e7c5e5c.so
236885 111322 4 348211 x86_64-unknown-linux-gnu/stage3/lib/librustc_back-4e7c5e5c.so
20742937 1035619 70464 21849020 x86_64-unknown-linux-gnu/stage3/lib/librustc_llvm-4e7c5e5c.so
1182102 508505 5280 1695887 x86_64-unknown-linux-gnu/stage3/lib/librustrt-4e7c5e5c.so
242924 690433 4 933361 x86_64-unknown-linux-gnu/stage3/lib/libserialize-4e7c5e5c.so
834141 1656905 344 2491390 x86_64-unknown-linux-gnu/stage3/lib/libstd-4e7c5e5c.so
151137 671324 4 822465 x86_64-unknown-linux-gnu/stage3/lib/libsync-4e7c5e5c.so
3322627 3880814 8 7203449 x86_64-unknown-linux-gnu/stage3/lib/libsyntax-4e7c5e5c.so
226532 107796 4 334332 x86_64-unknown-linux-gnu/stage3/lib/libterm-4e7c5e5c.so
46988 66785 4 113777 x86_64-unknown-linux-gnu/stage3/lib/libtime-4e7c5e5c.so

after
text data bss dec filename
15472 43201 4 58677 x86_64-unknown-linux-gnu/stage3/lib/libarena-4e7c5e5c.so
66250 68591 8 134849 x86_64-unknown-linux-gnu/stage3/lib/libdebug-4e7c5e5c.so
31659 3752 8 35419 x86_64-unknown-linux-gnu/stage3/lib/libflate-4e7c5e5c.so
20322 43650 4 63976 x86_64-unknown-linux-gnu/stage3/lib/libfmt_macros-4e7c5e5c.so
78261 78171 4 156436 x86_64-unknown-linux-gnu/stage3/lib/libgetopts-4e7c5e5c.so
10221 44019 4 54244 x86_64-unknown-linux-gnu/stage3/lib/libgraphviz-4e7c5e5c.so
34034 33703 200 67937 x86_64-unknown-linux-gnu/stage3/lib/liblog-4e7c5e5c.so
345751 153198 24 498973 x86_64-unknown-linux-gnu/stage3/lib/libnative-4e7c5e5c.so
48403 196039 8 244450 x86_64-unknown-linux-gnu/stage3/lib/librbml-4e7c5e5c.so
13491702 5253560 368 18745630 x86_64-unknown-linux-gnu/stage3/lib/librustc-4e7c5e5c.so
239161 99363 4 338528 x86_64-unknown-linux-gnu/stage3/lib/librustc_back-4e7c5e5c.so
20742865 1035050 70464 21848379 x86_64-unknown-linux-gnu/stage3/lib/librustc_llvm-4e7c5e5c.so
1186130 480401 5280 1671811 x86_64-unknown-linux-gnu/stage3/lib/librustrt-4e7c5e5c.so
245928 668157 8 914093 x86_64-unknown-linux-gnu/stage3/lib/libserialize-4e7c5e5c.so
838093 1597231 344 2435668 x86_64-unknown-linux-gnu/stage3/lib/libstd-4e7c5e5c.so
152177 653764 4 805945 x86_64-unknown-linux-gnu/stage3/lib/libsync-4e7c5e5c.so
3349091 3563279 8 6912378 x86_64-unknown-linux-gnu/stage3/lib/libsyntax-4e7c5e5c.so
229488 101380 4 330872 x86_64-unknown-linux-gnu/stage3/lib/libterm-4e7c5e5c.so
48156 54777 4 102937 x86_64-unknown-linux-gnu/stage3/lib/libtime-4e7c5e5c.so
```

## Difference (negative is better)
```
text data bss dec filename
455 33 -4 484 libarena-4e7c5e5c.so
40 -2669 4 -2625 libdebug-4e7c5e5c.so
0 -2 4 2 libflate-4e7c5e5c.so
184 -1852 -4 -1672 libfmt_macros-4e7c5e5c.so
1280 -5376 0 -4096 libgetopts-4e7c5e5c.so
-48 -418 -4 -470 libgraphviz-4e7c5e5c.so
488 -6668 0 -6180 liblog-4e7c5e5c.so
4324 -13186 0 -8862 libnative-4e7c5e5c.so
620 -11083 4 -10459 librbml-4e7c5e5c.so
167168 -1049627 0 -882459 librustc-4e7c5e5c.so
2276 -11959 0 -9683 librustc_back-4e7c5e5c.so
-72 -569 0 -641 librustc_llvm-4e7c5e5c.so
4028 -28104 0 -24076 librustrt-4e7c5e5c.so
3004 -22276 4 -19268 libserialize-4e7c5e5c.so
3952 -59674 0 -55722 libstd-4e7c5e5c.so
1040 -17560 0 -16520 libsync-4e7c5e5c.so
26464 - 317535 0 -291071 libsyntax-4e7c5e5c.so
2956 -6416 0 -3460 libterm-4e7c5e5c.so
1168 -12008 0 -10840 libtime-4e7c5e5c.so

-1356 liballoc-4e7c5e5c.rlib
1540 libarena-4e7c5e5c.rlib
160 libarena-4e7c5e5c.so
-74062 libcollections-4e7c5e5c.rlib
0 libcompiler-rt.a
-448244 libcore-4e7c5e5c.rlib
-58910 libdebug-4e7c5e5c.rlib
294 libdebug-4e7c5e5c.so
120 libflate-4e7c5e5c.rlib
-8 libflate-4e7c5e5c.so
-58534 libgetopts-4e7c5e5c.rlib
-4443 libgetopts-4e7c5e5c.so
-1992 libglob-4e7c5e5c.rlib
-767 libglob-4e7c5e5c.so
-4686 libgraphviz-4e7c5e5c.rlib
-384 libgraphviz-4e7c5e5c.so
-39866 libgreen-4e7c5e5c.rlib
-4547 libgreen-4e7c5e5c.so
0 liblibc-4e7c5e5c.rlib
-66714 liblog-4e7c5e5c.rlib
-9066 liblog-4e7c5e5c.so
0 libmorestack.a
-140108 libnative-4e7c5e5c.rlib
-10987 libnative-4e7c5e5c.so
-56826 libnum-4e7c5e5c.rlib
-2697 libnum-4e7c5e5c.so
-31722 librand-4e7c5e5c.rlib
-146418 librbml-4e7c5e5c.rlib
-10939 librbml-4e7c5e5c.so
-261958 libregex-4e7c5e5c.rlib
-22534 libregex-4e7c5e5c.so
0 librlibc-4e7c5e5c.rlib
-187366 librustrt-4e7c5e5c.rlib
-23967 librustrt-4e7c5e5c.so
-291182 librustuv-4e7c5e5c.rlib
-19400 librustuv-4e7c5e5c.so
-4722 libsemver-4e7c5e5c.rlib
2388 libsemver-4e7c5e5c.so
-284034 libserialize-4e7c5e5c.rlib
-19235 libserialize-4e7c5e5c.so
-655282 libstd-4e7c5e5c.rlib
-56009 libstd-4e7c5e5c.so
-328036 libsync-4e7c5e5c.rlib
-16513 libsync-4e7c5e5c.so
-74328 libterm-4e7c5e5c.rlib
-3352 libterm-4e7c5e5c.so
-198478 libtest-4e7c5e5c.rlib
-16490 libtest-4e7c5e5c.so
-148164 libtime-4e7c5e5c.rlib
-10166 libtime-4e7c5e5c.so
-1050 libunicode-4e7c5e5c.rlib
-38478 liburl-4e7c5e5c.rlib
-5015 liburl-4e7c5e5c.so
-35978 libuuid-4e7c5e5c.rlib
-3100 libuuid-4e7c5e5c.so
-3873611 total
```