Go Binary Sizes Have Been Pretty Stable

Update October 2nd 2024: This was updated to include Go versions all the way up to 1.23

In 2013 I wrote an unintentionally inflammatory post: Go Binary Sizes Are Growing out of Control. I had imagined no one would read it, but it took off. I wrote it because I noticed my binaries getting larger as I upgraded versions of Go and found it curious.

Much has changed since then; biggest of all there have a handful of major releases of Go in that time.

I wanted to find out how much this had changed since my post went up. I used Docker to automate the process of compiling against major releases of Go. The exact code I used is on GitHub.

I hit a couple of hurdles. The oldest official version of Go on Docker Hub is 1.2 - which happens to be the version my previous post left off. Also, many of the programs from the previous comparison no longer compile in such old versions of Go.

Thus, consider this a standalone comparison rather than a direct continuation of the previous post.

I ended up going through most of my Go projects to find what would actually compile in ancient versions of Go.

The tools I compiled for the comparison are in order

hello world using fmt

hello world using println

Hookah - a tool for GitHub automation

imgavg - a tool for averaging a collection of images

sqlread - a tool for querying MySQL dumps without loading them into a database.

The Results

Without further ado, the raw data in megabytes.

binary | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 | 1.7 | 1.8 | 1.9 | 1.10 | 1.11 | 1.12 | 1.13 | 1.14 | 1.15 | 1.16 | 1.17 | 1.18 | 1.19 | 1.20 | 1.21 | 1.22 | 1.23
hello-nofmt | 0.577 | 0.475 | 0.635 | 1.076 | 1.101 | 1.003 | 0.960 | 1.035 | 1.086 | 1.068 | 1.127 | 1.149 | 1.234 | 1.224 | 1.216 | 1.159 | 1.155 | 1.203 | 1.236 | 1.285 | 1.377 | 1.519
hello | 2.240 | 1.824 | 1.941 | 2.367 | 2.288 | 1.634 | 1.552 | 1.860 | 2.012 | 1.907 | 1.997 | 2.009 | 2.068 | 2.035 | 1.937 | 1.772 | 1.764 | 1.814 | 1.852 | 1.806 | 1.894 | 2.129
hookah | 8.352 | 6.737 | 6.868 | 7.684 | 8.739 | 6.391 | 6.553 | 6.805 | 7.311 | 7.282 | 8.234 | 8.289 | 8.315 | 7.191 | 6.907 | 6.848 | 7.014 | 7.260 | 7.477 | 7.620 | 7.892 | 8.464
imgavg | 3.793 | 3.040 | 3.089 | 3.607 | 3.560 | 2.736 | 2.529 | 2.656 | 2.854 | 2.766 | 2.891 | 2.920 | 2.978 | 2.887 | 2.802 | 2.569 | 2.558 | 2.629 | 2.676 | 2.619 | 2.748 | 2.970
sqlread | 4.730 | 3.648 | 3.739 | 4.242 | 4.192 | 3.170 | 3.043 | 3.091 | 3.284 | 3.144 | 3.302 | 3.316 | 3.373 | 3.265 | 3.149 | 2.989 | 2.968 | 3.057 | 3.110 | 3.171 | 3.291 | 3.538

Summary

The trendlines show the majority of the projects have a small downtick in size. The Go 1.5 and Go 1.6 releases caused a pretty universal uptick which 1.7 seems to have largely mitigated.

Hookah shows by far the most fluctuation in size by a pretty large margin. This is interesting because comparing dependencies the only builtin packages Hookah uses that sqlread does not are regexp and regexp/syntax. sqlread itself actually utilizes a pretty large number more. This could indicates the variation is deeper than the changes to the built in libraries, and potentially more to do with the compilation output and optimization.

Everything except for the simplest "Hello World" hello-nofmt has shown an overall decrease. hello-nofmt boils down to println("Hello, 世界") has shown an overall 658kb increase. This is likely the purest illustratration the growth in size of the runtime.

Conclusion

Go binaries are not "growing out of control". They're pretty stable and for the most part have shown a decrease.

I'm still hopeful future optimizations will help improve sizes. Given WASM becoming a major compilation target, size matters more than ever as it directly affect load times.