jLuger.de - Go revised: File size

In this post I will talk about the file size of programs written with Go. The compiled programs were very large and it was interesting to see what gccgo brought into the issue.

I had written in the last post that I need a system and webserver program. Well, it turned out that I needed two programs. Here is what they do.

Shrink: This program loads two files with json encoded data in it. With the data in them it builds a list of files and for each file it will call two external programs to shrink the file size.
73 lines of code.

Serve: This program builds a list of files and serves them via http. To build the list it has to read directories and load and parse json files. The files include a HTML 5 app, a list of workload history files and the files referenced in the workload history files.
155 line of code.

Files size:
Program
Size in Bytes
Shrink
1 791 430 (about 1.8 MB)
Serve
3 991 224 (about 3.9 MB)
Cshrink
41 486
Cserve
80 345

Update: Json and http server are part of Go runtime. The latter is only used in Serve. That will explaini the huge size difference for the static version.

The first two version were compiled into static programs using the go tool, while the second two were compiled with gccgo and have references to libraries. Using ldd on them gave me this:

    linux-vdso.so.1 =>  (0x00007fffb94c0000)
    libgo.so.0 => /usr/lib/x86_64-linux-gnu/libgo.so.0 (0x00007facc4578000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007facc4362000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007facc3fa2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007facc7272000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007facc3d85000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007facc3a89000)

Note: libgo alone has about 12MB making the smaller gccgo version in fact fatter.

To put this in a better context I've created three hello world programs. Two in pure C and one in C++.

File size again:

Program Size in Bytes
hello
8 706
hello2
8 811
hellopp
9 325

Thats very interesting. The C++ version is even larger than the extended C version but they all are about a fifth of the simple Shrink program. It gets more interesting when doing an ldd.

ldd on C:
    linux-vdso.so.1 =>  (0x00007ffff8bff000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f10322a2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f1032685000)

ldd on C++:
    linux-vdso.so.1 =>  (0x00007fff809ff000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7de2f33000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7de2b74000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7de2877000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f7de325a000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7de2661000)

Putting the data above together

The static binaries of gc are still ver large and even gccgo fails to get into regions of C/C++. Looking on the dependencies of the gccgo tells me that only libgo.so and lipthread.so are missing in the C++ version. I suppose libpthread would get into in when I needed threading. So compared to C++ I have only the libgo.so as an additional dependency.

Could I use go to build the userspace of a while distrubtion. With the static version definitely not. With the gccgo version maby. At this post (German) someone complains that a 500K binary could be done in 10K when they had used C instead of C++ with Boost. So the overhead of gccgo may be acceptable and 12MB per installation is nothing.

Is gc (static compiler) useless? No. I have seen organizations that provide a full Virtal Machine with an Java application server and several GB of RAM for each single application in order to ensure that the applications don't interfere. Compared to that the Go programs are ultra slim. Besides such extremes imagine you have written this cool php application and want to give it to a friend for testing. He needs to install apach and php to test it. With go you put some MB on dropbox and he loads it.

As seen gccgo and gc have both their strengths and you need to choose situationally one of them.