We all know that Golang has a significant feature: its compilation speed is extremely fast. The speed of compilation was a key consideration when Go was being designed. But have you ever looked at the size of the binary executable file produced after Go compiles your code? Let’s take a look at a simple HTTP server example.
This article was first published in the Medium MPP plan. If you are a Medium user, please follow me on Medium. Thank you very much.
|
|
The compiled size is 6.5M.
|
|
The Go compiler trims the size of the binary file. If you’re interested in this, check out my other article How Does the Go Compiler Reduce Binary File Size?.
Now let’s try to optimize the size of the server
.
Removing Debug Information
By default, the Go compiler includes a symbol table and debug information in the compiled program. Typically, you can remove this debug information for a release version to reduce the binary size.
|
|
-s
: Omit the symbol table and debug information.-w
: Omit the DWARFv3 debug information. With this option, you cannot use gdb to debug.
The size dropped from 6.5M to 4.5M, about a 30% reduction. This is a good first step.
Using UPX
UPX is an advanced executable file compressor. UPX will typically reduce the file size of programs and DLLs by around 50%-70%, thus reducing disk space, network load times, download times, and other distribution and storage costs.
On Mac, you can install UPX via brew
.
|
|
Compressing with UPX Alone
UPX has many parameters, with the most important being the compression ratio, ranging from 1-13. 1 represents the lowest compression ratio, and 13 is the highest.
Let’s see how much we can reduce the binary size using UPX alone.
|
|
The compression ratio is about 60%.
UPX + Compiler Options
Enabling both UPX and -ldflags="-s -w"
:
|
|
Finally, we get an executable file size of 1.4M compared to the uncompressed 6.5M, saving about 80% of the space. This is quite considerable for large applications.
How UPX Works
The compressed program works like the original and can run normally without decompression. This compression method is called shell compression, which includes two parts:
- Insert decompression code at the beginning or another suitable place in the program.
- Compress the rest of the program.
When executed, it also includes two parts:
- The decompression code inserted at the beginning is executed first, decompressing the original program into memory.
- Then, the decompressed program is executed.
UPX introduces an extra decompression step when the program is executed, but this time is almost negligible.
If you don’t have strict requirements on the compiled size, you might choose not to use UPX compression. Generally, server-side standalone background services do not need compressed size.
Conclusion
This post contains many interesting answers:
- For example, when implementing the same functionality with C and Go (a small demo), the executable size generated by C is 1/20th of that generated by Go (why?).
- Using
println
instead offmt.Println
can avoid importing thefmt
package, further reducing the size.