I'm curious what kinds of tasks require a binary with a 300 MB text size…
I'm curious what kinds of tasks require a binary with a 300 MB text size…
C++ lends itself to bloated binaries. Template instantiations are duplicated even for types where the instantiations could have identical code. Compilers have traditionally favored overly aggressive inlining over whole-program optimization.
Rust didn't solve the problem; it just duplicated the C++ approach, and made it worse by effectively compiling with the equivalent of C++ exceptions enabled. The next great systems language should target binary size and CPU frontend overhead.
compilers and linkers had identical code folding optimizations for a looooong time (20+ years for msvc, a decade or so for GNU gold (--icf option) and GCC (-fipa-icf))
On my machine I get no unsigned instantiation, only the signed one :
$ objdump -D a.out | c++filt | grep foo
563: e8 21 01 00 00 callq 689 <bool foo<int>(int)>
56c: e8 18 01 00 00 callq 689 <bool foo<int>(int)>
0000000000000689 <bool foo<int>(int)>:
and the main : 0000000000000560 <main>:
560: 53 push %rbx
561: 31 ff xor %edi,%edi
563: e8 21 01 00 00 callq 689 <bool foo<int>(int)>
568: 31 ff xor %edi,%edi
56a: 89 c3 mov %eax,%ebx
56c: e8 18 01 00 00 callq 689 <bool foo<int>(int)>
571: 0f b6 d3 movzbl %bl,%edx
574: 48 8d 3d b1 01 00 00 lea 0x1b1(%rip),%rdi # 72c <_IO_stdin_used+0x4>
57b: 0f b6 f0 movzbl %al,%esi
57e: 31 c0 xor %eax,%eax
580: e8 cb ff ff ff callq 550 <printf@plt>
585: 31 c0 xor %eax,%eax
587: 5b pop %rbx
588: c3 retq
589: 00 00 add %al,(%rax)
58b: 00 00 add %al,(%rax)
58d: 00 00 add %al,(%rax)If you look at the resulting binaries, they don't work as well as you might think.
This means the compiler will automatically detect how much duplication is actually needed ahead of time, eliminating the need for after-the-fact identical code folding. (This should also drastically reduce compile times for some programs!)
And it could go even further than that. For example, some code could be duplicated based only on the size+alignment of its parameters (C#-style generics without a JIT). The analysis could be finer-grained than per-function, sharing parts of a function across instantiations (kind of like outlining).
With the detection happening this early in the pipeline, the compiler could even tell the user about it and guide them toward techniques that reduce the amount of duplication. (A different language could go further, of course.)
I repro here some data, there is a bit more in the paper:
Clang 1.9k Files, 217MB (-g0), 3554MB (-g) Chromium 17.8k Files 706MB (-g0), 7544MB (-g) Ad Delivery 13.8k Files 1073MB (-g0), 7469MB (-g)
(this is the number of object file that are participating in the link).
Ah, that would probably be it.