go-size-analyzer:把一个 Go 二进制"拆开称重量"的开源工具

Go
可观测性
二进制瘦身
开源
DevOps
2026/9/30
·

阅读时间: 大约 9 分钟

go-size-analyzer:把一个 Go 二进制”拆开称重量”的开源工具

go-size-analyzer 的 Web/treemap 视图:对象为 docker-compose-linux-x86_64,绿色为标准库包(Std Packages)、蓝色为第三方 vendor 包、红色为无法归属的 section(.noptrdata/.text/.symtab/.gopclntab/.rodata/.strtab)

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/api11 MBvendor
15.52%.rodata9.8 MBsection
8.92%.gopclntab5.6 MBsection
7.51%.strtab4.7 MBsection
5.13%k8s.io/client-go3.2 MBvendor
3.36%.symtab2.1 MBsection
3.29%github.com/moby/buildkit2.1 MBvendor
2.02%google.golang.org/protobuf1.3 MBvendor
1.40%runtime884 kBstd

go-size-analyzer 输出的 svg treemap(示例对象 cockroach-darwin-amd64,--hide-sections):矩形面积正比于体积,可逐层下钻到具体包与文件

这组数据揭示了一个常被忽略的事实:Go 二进制的体积大头不只是业务依赖,还有段信息——.rodata、.gopclntab(函数行号表)、.strtab、.symtab 加起来占了相当比例。也就是说,瘦身不能只盯着”删哪个库”,还要看 release 构建是否保留了符号表与调试段。

三、diff 模式:版本升级带来了多少体积变化

README 还演示了对比 bin-linux-1.21-amd64 与 bin-linux-1.22-amd64:

名称旧体积新体积变化
runtime801 kB1.0 MB+230 kB(+28.69%)
internal/chacha8rand—3.1 kB新增(+100%)
.rodata122 kB132 kB+10 kB(+8.47%)
.gopclntab144 kB152 kB+7.3 kB
二进制整体1.6 MB1.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 的构建上分析以获得准确结论,再结合自己的发布参数(是否剥离符号表)去解读数字。

参考来源