我编译了一个hello world Go程序,它在我的linux机器上生成了本地可执行文件。但我惊讶地看到简单的Hello world Go程序的大小是1.9MB!
为什么Go中这么简单的程序的可执行文件如此之大?
发布于 2015-02-18 16:32:54
这个问题出现在官方常见问题解答中:
引用答案:
gc工具链中的链接器(
5l、6l和8l)执行静态链接。因此,所有的Go二进制文件都包含Go运行时,以及支持动态类型检查、反射、甚至死机时堆栈跟踪所需的运行时类型信息。
一个简单的C "hello,world“程序在Linux上使用gcc静态编译和链接,包括printf的实现,大约是750 kB。使用fmt.Printf的等效Go程序大约为1.9MB,但这包括更强大的运行时支持和类型信息。
因此,Hello World的本机可执行文件是1.9MB,因为它包含一个运行时,该运行时提供垃圾收集、反射和许多其他特性(您的程序可能并不真正使用这些特性,但它确实存在)。以及用于打印"Hello World"文本(及其依赖项)的fmt包的实现。
现在尝试执行以下操作:在程序中添加另一个fmt.Println("Hello World! Again")行,然后重新编译它。结果将不是2x1.9MB,但仍然只有1.9MB!是的,因为所有使用过的库(fmt及其依赖项)和运行时都已经添加到可执行文件中(所以只需要添加几个字节就可以打印出您刚刚添加的第二个文本)。
发布于 2017-09-11 23:16:41
考虑以下程序:
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}如果我在我的Linux AMD64机器(GO1.9)上构建它,如下所示:
$ go build
$ ls -la helloworld
-rwxr-xr-x 1 janf group 2029206 Sep 11 16:58 helloworld我得到一个大小约为2Mb的二进制文件。
这样做的原因(在其他答案中已经解释过了)是因为我们使用的是"fmt“包,它相当大,但二进制文件也没有被剥离,这意味着符号表仍然存在。如果我们改为指示编译器剥离二进制文件,它将变得更小:
$ go build -ldflags "-s -w"
$ ls -la helloworld
-rwxr-xr-x 1 janf group 1323616 Sep 11 17:01 helloworld但是,如果我们重写程序以使用内置函数print,而不是fmt.Println,如下所示:
package main
func main() {
print("Hello World!\n")
}然后编译它:
$ go build -ldflags "-s -w"
$ ls -la helloworld
-rwxr-xr-x 1 janf group 714176 Sep 11 17:06 helloworld我们最终得到了一个更小的二进制文件。这是我们在不使用UPX打包的情况下所能得到的最小的开销,所以Go-runtime的开销大约是700KB。
发布于 2015-02-18 14:34:38
请注意,golang/go project中的issue 6853会跟踪二进制大小问题。
例如,commit a26c01a (对于Go 1.4) 将hello world减少了70kB
,因为我们不会将这些名称写入符号表。
考虑到1.5的编译器、汇编器、链接器和运行时将完全在Go中运行,您可以期待进一步的优化。
更新2016 Go 1.7:已优化:请参阅"Smaller Go 1.7 binaries“。
但如今(2019年4月),占据最多位置的是。
参见中的"Why are my Go executable files so large? Size visualization of Go executables using D3“。
它并没有很好的文档记录,但是Go源代码中的这条评论暗示了它的用途:
// LineTable是将程序计数器映射到行号的数据结构。
此数据结构的目的是使Go运行时系统能够通过runtime.GetStack应用程序接口在崩溃或内部请求时生成描述性堆栈跟踪。
所以它看起来很有用。但是为什么它这么大呢?
隐藏在上述重新链接的源文件中的URL https://golang.org/s/go12symtab重定向到一个文档,该文档解释了Go 1.0和1.2之间发生的事情。转述如下:
在1.2之前,Go链接器发出一个压缩的行表,程序会在运行时初始化时对其进行解压缩。
在Go 1.2中,决定将可执行文件中的行表预先扩展为适合在运行时直接使用的最终格式,而不需要额外的解压缩步骤。
换句话说,Go团队决定让可执行文件变得更大,以节省初始化时间。
此外,从数据结构来看,除了每个函数的大小外,它在编译后的二进制文件中的总大小似乎与程序中函数的数量呈超线性关系。

https://stackoverflow.com/questions/28576173
复制相似问题