hello world executable size

Joakim via Digitalmars-d digitalmars-d at puremagic.com
Thu Jun 25 04:04:59 PDT 2015


I was curious if binary sizes had decreased because of the 
changes Ilya had been making to try and scope imports better and 
make them more selective:

https://github.com/D-Programming-Language/phobos/pulls?utf8=%E2%9C%93&q=is%3Apr+author%3A9il+clean

Hello world (void main(){ import std.stdio; writefln("hello 
roboto"); }) size went from 464 KB to 548 KB when going from 
2.066.1 to 2.067.1 on linux/x86, an increase of 18% (dmd -O 
-release main.d).  I used nm to try and find some of the symbols 
using the most space (command taken from SO):

nm -B -r --size-sort --print-size -t d main

I noticed that the symbol taking up the third-most space was 
_d_arraysetlengthT, which wasn't in the older executable 
generated by 2.066.1.  Disassembling the newer executable 
(objdump -rD main), it appears that it's called from exactly one 
function, std.uni.GcPolicy.realloc, which is in turn only called 
from one templated struct's member function, 
std.uni.CowArray.length.  That instantiated function isn't called 
from anywhere else in the binary.

The templated struct std.uni.CowArray is only instantiated by the 
templated struct std.uni.InversionList in the source, but I'm not 
sure why neither is instantiated in the older executable and a 
diff of the two versions of std.stdio doesn't produce anything 
that stands out.  None of this appears to be used when the binary 
is run, as having gdb break on _d_arraysetlengthT does nothing.

But std.uni isn't actually imported directly by std.stdio, where 
does it come from?  Nearest I can tell from adding the -v flag to 
dmd, std.stdio has a couple scoped, selective imports to some 
functions from std.utf.  std.utf has exactly _one_ scoped, 
selective import of std.string.format in its UTFException class, 
and std.string has several selective imports from std.uni, 
including one at module scope.

I tried commenting out that single selective import of 
std.string.format in std.utf and the same binary compiled and ran 
fine without any imports of std.string or std.uni, plus it was 
now 36 KB smaller. :)

I realize executable size may not be a priority, but this 
exploration shows how easy it is to get a bunch of template 
garbage pulled in to executables (I know this is not news for 
some).  Perhaps the binary would have been twice as big if not 
for Ilya's work!  Maybe this isn't considered something that 
should be fixed at the compiler level, but rather by properly 
working with the linker to remove these, as David did with 
--gc-sections for ldc.  Either way, some kind of dashboard that 
charts binary sizes for dmd PRs can't come soon enough, so we can 
keep better tabs on this.


More information about the Digitalmars-d mailing list