go-size-analyzer:把一个 Go 二进制"拆开称重量"的开源工具
阅读时间: 大约 9 分钟
go-size-analyzer:把一个 Go 二进制”拆开称重量”的开源工具

Go 以”编译成单文件”著称,但随着依赖增多,二进制体积膨胀常令人头疼:一个 docker-compose 构建产物可以到 63 MB,而你很难知道体积到底花在哪个包、哪个 section。开源工具 go-size-analyzer(命令名 gsa,作者 Zxilly)就是为回答”依赖到底让我的二进制胖了多少”而生。它支持跨平台分析 ELF、Mach-O、PE 以及实验性的 WebAssembly 二进制,按包与 section 给出明细,并提供 text、json、html、svg 多种输出格式,还带 Web 界面、终端 UI 与二进制 diff 模式。
一、它能做什么
按 README,gsa 的核心能力包括:
- 跨平台解析四种二进制格式(Wasm 为实验性);
- 按**包(package)与段(section)**两个维度做体积分解;
- 输出格式
text、json、html、svg; - 通过
--web起本地服务(默认 8080)在浏览器里交互式下钻,或--tui在终端里探索; - diff 模式:对比两个二进制(或两份 json 结果)的体积变化;
- 可选
--no-disasm、--no-symbol、--no-dwarf跳过某些解析阶段。
安装方式也很直接:macOS/Linux 用 brew install go-size-analyzer,Windows 用 scoop install go-size-analyzer,或 go install github.com/Zxilly/go-size-analyzer/cmd/gsa@latest。需要注意:从源码构建需要 Go 1.27 或更高版本,因为项目用了 encoding/json/v2。
二、可核对的实测数据:docker-compose 63 MB 去哪了
README 给出了对 docker-compose-linux-x86_64 的 text 模式分析结果,TOTAL 与 KNOWN 均为 63 MB。占比前列如下(直接摘自 README 示例):
| 占比 | 名称 | 体积 | 类型 |
|---|---|---|---|
| 17.37% | k8s.io/api | 11 MB | vendor |
| 15.52% | .rodata | 9.8 MB | section |
| 8.92% | .gopclntab | 5.6 MB | section |
| 7.51% | .strtab | 4.7 MB | section |
| 5.13% | k8s.io/client-go | 3.2 MB | vendor |
| 3.36% | .symtab | 2.1 MB | section |
| 3.29% | github.com/moby/buildkit | 2.1 MB | vendor |
| 2.02% | google.golang.org/protobuf | 1.3 MB | vendor |
| 1.40% | runtime | 884 kB | std |
这组数据揭示了一个常被忽略的事实:Go 二进制的体积大头不只是业务依赖,还有段信息——.rodata、.gopclntab(函数行号表)、.strtab、.symtab 加起来占了相当比例。也就是说,瘦身不能只盯着”删哪个库”,还要看 release 构建是否保留了符号表与调试段。
三、diff 模式:版本升级带来了多少体积变化
README 还演示了对比 bin-linux-1.21-amd64 与 bin-linux-1.22-amd64:
| 名称 | 旧体积 | 新体积 | 变化 |
|---|---|---|---|
| runtime | 801 kB | 1.0 MB | +230 kB(+28.69%) |
| internal/chacha8rand | — | 3.1 kB | 新增(+100%) |
| .rodata | 122 kB | 132 kB | +10 kB(+8.47%) |
| .gopclntab | 144 kB | 152 kB | +7.3 kB |
| 二进制整体 | 1.6 MB | 1.6 MB | +61 kB(+3.86%) |
这种 diff 能力在升级 Go 版本、替换依赖或做 CI 体积护栏时很实用:能精确回答”这次构建为什么变大了”。
四、评测口径与局限
gsa 是个分析工具,不是优化工具本身,使用时要清楚它的口径边界:
- stripped 二进制结果可能不准:README 在 Caution 中明确警告,工具能处理 strip 过的二进制,但可能导致结果不准确。如果你发布时
-s -w剥离了符号表,分析结论要打折扣。 - Wasm 浏览器版慢约 10 倍:README 注明浏览器里的 WebAssembly 版本因限制比原生慢约 10×,只建议分析 30 MB 以下的小应用。
- 它只测静态体积,不测运行时内存或性能:二进制小不等于内存占用低,也不代表启动快。
- AGPL-3.0 许可:项目以 AGPL-3.0 发布。作为命令行工具自己用没问题,但如果想把它的能力嵌入到商业产品或 SaaS 里,需要注意 AGPL 的强 copyleft 传染性。
- 功能仍在 TODO:README 的 TODO 列出了尚未完成的能力——更多反汇编模式、从 DWARF 段提取更多信息、按函数符号尺寸归并到包、火焰图/饼图等更多图表、cgo 下 C++/Rust 符号 demangling。也就是说,现在的 treemap/text 是主力形态,更丰富的可视化还在路上。
五、适用与不适用场景
- 适合:维护 CLI 工具、单文件分发服务、追求镜像/二进制体积的团队;在 CI 里加一道”体积 diff 不超标”的护栏;定位某个依赖为何突然让产物变大。
- 适合结合:分析后再配合
-ldflags "-s -w"剥离调试信息、garble混淆、或裁剪未用依赖来实际瘦身——gsa 负责”诊断”,不负责”治疗”。 - 不适合:已经 strip 到信息不全的发布产物(结论不可靠);超大二进制走浏览器 Wasm 版(慢);想直接拿到运行时 profile(那是 pprof/pprof-torch 的领域)。
六、它意味着什么
go-size-analyzer 把 Go 二进制的”黑箱体积”变成了可下钻的明细,尤其强调了”段信息”和”包依赖”两个常被混淆的维度。对追求发布物轻量的 Go 团队,它是一个轻量、跨平台、有 diff 能力的诊断起点。用它时只要记住两点:先在未 strip 的构建上分析以获得准确结论,再结合自己的发布参数(是否剥离符号表)去解读数字。