golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/blog/content/go1.7-binary-size.article (about) 1 Smaller Go 1.7 binaries 2 18 Aug 2016 3 4 David Crawshaw 5 crawshaw@golang.org 6 7 * Introduction 8 9 Go was designed for writing servers. 10 That is how it is most widely used today, and as a result a lot of 11 work on the runtime and compiler is focused on issues that matter to 12 servers: latency, ease of deployment, precise garbage collection, 13 fast startup time, performance. 14 15 As Go gets used for a wider variety of programs, there are new issues that must be considered. 16 One of these is binary size. 17 It has been on the radar for a long time 18 (issue [[https://golang.org/issue/6853][#6853]] was filed over two 19 years ago), but the growing interest in using Go for 20 deploying binaries on smaller devices — such as the Raspberry Pi or 21 mobile devices — means it received some attention for the Go 1.7 22 release. 23 24 * Work done in Go 1.7 25 26 Three significant changes in Go 1.7 affect binary size. 27 28 The first is the new SSA backend that was enabled for AMD64 in this release. 29 While the primary motivation for SSA was improved performance, the 30 better generated code is also smaller. 31 The SSA backend shrinks Go binaries by ~5%. 32 We expect larger gains for the more RISC-like architectures 33 like ARM and MIPS when those backends have been converted to SSA in Go 1.8. 34 35 The second change is method pruning. 36 Until 1.6, all methods on all used types were kept, even if some of 37 the methods were never called. 38 This is because they might be called through an interface, or called 39 dynamically using the reflect package. 40 Now the compiler discards any unexported methods that do not match an 41 interface. 42 Similarly the linker can discard other exported methods, those that are only 43 accessible through reflection, if the corresponding 44 [[https://golang.org/pkg/reflect/#Value.Call][reflection features]] 45 are not used anywhere in the program. 46 That change shrinks binaries by 5–20%. 47 48 The third change is a more compact format for run-time type 49 information used by the reflect package. 50 The encoding format was originally designed to make the decoder in 51 the runtime and reflect packages as simple as possible. By making this 52 code a bit harder to read we can compress the format without affecting 53 the run-time performance of Go programs. 54 The new format shrinks Go binaries by a further 5–15%. 55 Libraries built for Android and archives built for iOS shrink further 56 as the new format contains fewer pointers, each of which requires 57 dynamic relocations in position independent code. 58 59 In addition, there were many small improvements such as improved 60 interface data layout, better static data layout, and simplified 61 dependencies. For example, the HTTP client no longer links in the entire HTTP 62 server. 63 The full list of changes can be found in issue 64 [[https://golang.org/issue/6853][#6853]]. 65 66 * Results 67 68 Typical programs, ranging from tiny toys to large production programs, 69 are about 30% smaller when built with Go 1.7. 70 71 The canonical hello world program goes from 2.3MB to 1.6MB: 72 73 package main 74 75 import "fmt" 76 77 func main() { 78 fmt.Println("Hello, World!") 79 } 80 81 When compiled without debugging information the statically 82 linked binary is now under a megabyte. 83 84 .image go1.7-binary-size.png 85 86 A large production program used for testing this cycle, `jujud`, went from 94MB 87 to 67MB. 88 89 Position-independent binaries are 50% smaller. 90 91 In a position-independent executable (PIE), a pointer in a read-only 92 data section requires a dynamic relocation. 93 Because the new format for type information replaces pointers by 94 section offsets, it saves 28 bytes per pointer. 95 96 Position-independent executables with debugging information removed 97 are particularly important to mobile developers, as this is the kind 98 of program shipped to phones. 99 Big downloads make for a poor user experience, so the reduction here 100 is good news. 101 102 * Future Work 103 104 Several changes to the run-time type information were too late for the 105 Go 1.7 freeze, but will hopefully make it into 1.8, further shrinking 106 programs, especially position-independent ones. 107 108 These changes are all conservative, reducing binary size without increasing 109 build time, startup time, overall execution time, or memory usage. 110 We could take more radical steps to reduce binary size: the 111 [[http://upx.sourceforge.net/][upx]] tool for compressing executables 112 shrinks binaries by another 50% at the cost of increased startup time 113 and potentially increased memory use. 114 For extremely small systems (the kind that might live on a keychain) 115 we could build a version of Go without reflection, though it is 116 unclear whether such a restricted language would be sufficiently 117 useful. 118 For some algorithms in the runtime we could use slower but more 119 compact implementions when every kilobyte counts. 120 All of these call for more research in later development cycles. 121 122 To the many contributors who helped make Go 1.7 binaries smaller, 123 thank you!