Go 1.7 将产生更小的二进制包

未匹配的标注

本文为官方 Go Blog 的中文翻译,详见 翻译说明

David Crawshaw
2016年8月18日

Introduction

介绍

Go是为编写服务器而设计的。这就是当今最广泛使用的方式,因此,运行时和编译器上的许多工作都集中在与服务器相关的问题上:延迟,易于部署,精确的垃圾收集,快速的启动时间,性能。

随着Go广泛用于各种程序,必须考虑一些新问题。其中之一是二进制大小。它已经很长时间了(问题#6853在两年前提交),但是对于使用Go在较小的设备上部署二进制文件的兴趣日益浓厚-例如Raspberry Pi或移动设备-意味着它在Go 1.7版本中受到了关注。

Go 1.7中完成的工作

Go 1.7中的三个重要更改会影响二进制大小。

首先是在此版本中为AMD64启用的新SSA后端。虽然提高SSA的主要动机是提高性能,但生成更好的代码也更小。 SSA后端将Go二进制文件缩小了5%。当这些后端已在Go 1.8中转换为SSA时,我们期望像ARM和MIPS这样的类似RISC的体系结构会获得更大的收益。

第二个变化是方法修剪。在1.6版之前,即使从未调用过某些方法,所有使用的类型的所有方法都将保留。这是因为它们可能是通过接口调用的,也可能是使用反射包动态调用的。现在,编译器将丢弃任何与接口不匹配的未导出方法。同样,如果程序中的任何地方未使用相应的reflection features,则链接器可以丢弃其他只能通过反射访问的导出方法。这种变化使二进制文件缩小了5-20%。

第三个变化是反射包使用的运行时类型信息的格式更紧凑。最初设计编码格式是为了使解码器在运行时运行并尽可能简单地反映包。通过使这段代码更难阅读,我们可以压缩格式而不会影响Go程序的运行时性能。新格式会将Go二进制文件进一步缩小5–15%。随着新格式包含更少的指针,为Android构建的库和为iOS构建的档案会进一步缩小,每个指针都需要在位置无关代码中进行动态重定位。

此外,还有许多小的改进,例如改进的接口数据布局,更好的静态数据布局和简化的依赖关系。例如,HTTP客户端不再链接到整个HTTP服务器。完整的更改列表可以在问题#6853中找到。

结果

使用Go 1.7构建的典型程序(从微型玩具到大型生产程序)要小30%。

规范的hello world程序从2.3MB扩展到1.6MB:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

当不使用调试信息进行编译时,静态链接的二进制文件现在不到1兆字节。.

用于测试此循环的大型生产程序jujud从94MB减小到67MB。

与位置无关的二进制文件小50%。

在位置无关的可执行文件(PIE)中,只读数据节中的指针需要动态重定位。由于类型信息的新格式将指针替换为节偏移量,因此每个指针可节省28个字节。

除去调试信息的位置无关的可执行文件对移动开发人员尤其重要,因为这是手机附带的程序。大下载量会带来糟糕的用户体验,因此减少下载量是个好消息。

未来的工作

对于Go 1.7冻结,对运行时类型信息的一些更改为时已晚,但希望将其更改为1.8,从而进一步缩小程序,尤其是与位置无关的程序。

这些更改都是保守的,在不增加构建时间,启动时间,总体执行时间或内存使用量的情况下减小了二进制文件的大小。我们可以采取更激进的步骤来减少二进制文件的大小:用于压缩可执行文件的upx工具将二进制文件再压缩50%,代价是增加了启动时间并可能增加了内存使用量。对于非常小的系统(可能存在于钥匙串中的那种系统),我们可以构建一个不带反射的Go版本,尽管尚不清楚这种受限制的语言是否足够有用。对于运行时中的某些算法,当每千字节计数时,我们可以使用更慢但更紧凑的实现。所有这些都要求在以后的开发周期中进行更多的研究。

对于帮助缩小Go 1.7二进制文件的许多贡献者,谢谢!

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/go-blog/go1.7-b...

译文地址:https://learnku.com/docs/go-blog/go1.7-b...

上一篇 下一篇
Summer
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~