- Published on
The 4.9MB question
- Authors
- Name
- Jo Guerreiro
The premise
Morgana called my attention in #278 to something interesting:
Also while testing gccgo creates a yay binary of size 1.5MB (probably because it links dynamically to alpm.so) go creates a yay binary of size 4.7MB gccgo has an install size of 149MB and download size of 22MB go has an install size of 330MB and download size of 67MB
I was also curious what led to such a difference. My suspicion was the static linking of the go runtime was done by default in go
but not gcc-go
First I created a binary from the same release yay-gcc
for the gccgo and yay-go
for the go version. Both were built using go build
(using the respective compiler) so they were not stripped (yay-gcc
had 2.4MB and yay-go
had 7.3MB)
Testing
ldd
Running ldd
to check the direct and indirect libs needed, was already revealing. ldd yay-go
displayed 31 lines and ldd yay-gcc
displayed 34 lines. In both cases /usr/lib/alpm.so.10
was linked.
diff
libgo.so.11
libm.so.6
libgcc_s.so.1
Using pkgfile -s
on each file these packages belong to core/gcc-libs and core/glibc
readelf
Running readelf -d binary | grep NEEDED
will return our direct dependencies
yay-go
0x0000000000000001 (NEEDED) Shared library: [libalpm.so.10]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
yay-gcc
0x0000000000000001 (NEEDED) Shared library: [libalpm.so.10]
0x0000000000000001 (NEEDED) Shared library: [libgo.so.11]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
So we can estimate the size of the go runtime in yay
to be 3.2MB
when the binaries are stripped and 4.9MB
when not stripped.
radare2
As a comparison I decided to analyze using radare2 the amount of function symbols present using: radare2
and exporting symbols grepping FUNC
$ radare2 yay-go
[0x00405920]> is~FUNC > yay-go.txt
q
$ wc yay-go.txt
6014 42486 459696 yay-go.txt
$ radare2 yay-gcc
[0x00405920]> is~FUNC > yay-gcc.txt
q
$ wc yay-gcc.txt
1574 11018 132556 yay-gcc.txt
Roughly a 4440 FUNC symbol difference is noticeable between the 2.
Benchmarking
I would have liked to do proper benchmarking of the 2 binaries, unfortunately it was a bit too much work to set up a reproducible environment to run yay -Syu
a 100 times, even without taking into account networking.
On a system without any updates available:
$ time ./yay-gcc -Syu
1.04user 0.08system 0:02.35elapsed 47%CPU (0avgtext+0avgdata 73832maxresident)k
0inputs+96outputs (0major+29015minor)pagefaults 0swaps
$ time ./yay-go -Syu
0.76user 0.03system 0:01.77elapsed 45%CPU (0avgtext+0avgdata 36548maxresident)k
0inputs+80outputs (0major+18211minor)pagefaults 0swaps
After reproducing the same test a couple of times yay-go
(as predicted) has a better performance than yay-gcc
(the go
compiler is more optimized than gcc-go
according to some sources online, and accessing linked libraries is always slower).
$ time ./yay-gcc -Ps
0.33user 0.02system 0:00.61elapsed 58%CPU (0avgtext+0avgdata 72988maxresident)k
0inputs+0outputs (0major+11321minor)pagefaults 0swaps
$ time ./yay-go -Ps
0.24user 0.02system 0:00.36elapsed 72%CPU (0avgtext+0avgdata 36204maxresident)k
0inputs+0outputs (0major+6969minor)pagefaults 0swaps
Conclusions
So to conclude:
- The 4.9MB difference is due to the static linking of the go runtime in
yay-go
. yay-go
is still faster thanyay-gcc
by about a100%
in mediocrely done benchmarking.