4 ms·
> 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 f
by cwzwarich 7y ago
> 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.
- jcelerier 7y ago> Template instantiations are duplicated even for types where the instantiations could have identical code. 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))
- saagarjha 7y agoI was going to reply with a similar comment, but I'm unable to actually get this to happen when I tried it now: https://godbolt.org/z/4VkEQc https://godbolt.org/z/4VkEQc. Perhaps the optimization needs more work?
- jcelerier 7y agoNo, it's just that the assembly output of godbolt happens before these optimization phases. 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)
- cwzwarich 7y ago> 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)) If you look at the resulting binaries, they don't work as well as you might think.
- eska 7y agoNot sure why you get downvoted. I've seen presentations by Ubisoft for example where they replaced templated vectors because of the code bloat which added up too much in their large code base.
- steveklabnik 7y ago(That’s only by default, you can panic=abort and not get that overhead too.)
- Rusky 7y agoRust still has some room to improve over C++ here. Because it knows up-front which operations generic code can use on its type parameters, it can do things like "polymorphization": https://github.com/rust-lang/rust/pull/69749 https://github.com/rust-lang/rust/pull/69749 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.)