Go1.25 新特性:引入 DWARF5,鏈接器更快,二進制文件更小了!
大家好,我是煎魚。
Go 這一門編程語言,在推出時,相較個別語言來講,編譯后較為小的二進制文件是一個較大的賣點。
而本次在 Go1.25 新特性中,又針對縮小編譯后二進制文件有了新的改善。今天分享給大家。
新提案:compile 使用 DWARF5
這個新提案《cmd/compile: consider using DWARF 5[1]》由 @Austin Clements 在 2018 年提出:
目的是期望在 Go1.25 新版本中在 Go 編譯器使用 DWARF5 版本。
Go 使用 DWARF 版本情況
Go 版本 | 默認 DWARF 版本 | 說明 |
Go 1.0 - 1.9 | DWARF v2 | 使用較老的 DWARF 格式,結構簡單、兼容性強,但體積大、功能有限。 |
Go 1.10 | DWARF v4 引入(部分支持) | 初步支持 DWARF v4,但并非所有平臺默認啟用。 |
Go 1.11 - 1.17 | DWARF v4(默認) | 廣泛采用 DWARF v4,改進了范圍列表、位置表達式等。調試體驗顯著提升。 |
Go 1.18+ | DWARF v4(壓縮優化) | 在 v4 基礎上對 |
Go 1.20+ | DWARF v4 + Zlib 壓縮(可選) | 支持壓縮 DWARF 區段,縮小二進制體積,但仍為 v4。 |
Go 1.22+ | DWARF v4 + 支持 position-independent DWARF | 支持位置無關調試信息(如 DWARFv5 的一部分理念),但仍標注為 v4。 |
DWARF5 背景和優勢
現階段 DWARF5 還是比較新的輪子,于 2017 年發布。
在 DWARF5 的生態圈中,GNU 和 LLVM 工具鏈以及一些調試器都支持 DWARF5 。
GCC7.1(2017 年 5 月)和 GDB8.0(2017 年 6 月)中添加了支持大多數 Xcode 工具也支持。因此作者關注到了他。
DWARF 一共有以下幾個正式版本:
原作者認為 DWARF5 與以前的 DWARF 版本相比,是具體以下幾個優勢的:
- 支持位置無關的表示方式,這大大減少了目標文件中的重定位數量:
從而減小了目標文件的體積并減輕了鏈接器的負擔。
在 Go 可執行文件中,503,361 個總重定位記錄中有 49% 來自 DWARF。
- 支持更為緊湊的位置與范圍列表格式:即便使用 zlib 壓縮,位置和范圍列表區段也僅占 12MiB Go 可執行文件的 6%。
- 為 Go 提供了官方的語言代碼。
基準測試結果
根據原作者提供的基準測試結果[2],修改后(啟用 DWARF 5)與修改前(原版本)的對比可以得出以下結論:
│ out.base.txt │ out.dwarf5.txt │
│ sec/op │ sec/op vs base │
Template 61.56m ± 1% 61.28m ± 1% ~ (p=0.136 n=50)
Unicode 45.54m ± 1% 45.32m ± 1% ~ (p=0.145 n=50)
GoTypes 348.9m ± 0% 347.1m ± 1% -0.52% (p=0.014 n=50)
Compiler 47.94m ± 1% 47.04m ± 2% ~ (p=0.061 n=50)
SSA 2.880 ± 1% 2.863 ± 0% -0.61% (p=0.003 n=50)
Flate 36.76m ± 1% 36.28m ± 1% -1.31% (p=0.001 n=50)
GoParser 70.02m ± 1% 69.50m ± 1% -0.75% (p=0.028 n=50)
Reflect 178.6m ± 1% 175.6m ± 1% -1.67% (p=0.000 n=50)
Tar 75.51m ± 1% 74.51m ± 1% -1.33% (p=0.001 n=50)
XML 86.60m ± 1% 86.48m ± 1% ~ (p=0.688 n=50)
LinkCompiler 297.5m ± 3% 295.8m ± 4% ~ (p=1.000 n=50)
ExternalLinkCompiler 1035.6m ± 1% 887.2m ± 1% -14.33% (p=0.000 n=50)
LinkWithoutDebugCompiler 168.0m ± 4% 166.8m ± 3% ~ (p=0.571 n=50)
StdCmd 14.27 ± 1% 14.16 ± 0% -0.78% (p=0.000 n=50)
geomean 208.8m 204.9m -1.89%
...
- 外部鏈接器性能提升顯著:
ExternalLinkCompiler
測試結果顯示sec/op
鏈接時間降低了-14.33%
。說明 DWARF5 顯著減少了外部鏈接器處理的壓力,可能是relocations
或.debug_*
區段大幅簡化。 - 用戶態耗時有輕微優化:
user-sec/op
平均減少約 2.67%,表明在構建、鏈接等過程中均有輕微的優化效果。 - 可執行文件體積降低:可執行文件總大小平均下降 3%,可視為 DWARF5 更緊湊的調試信息格式的直接成果。
- 綜合無明顯退化表現:沒有一個 benchmark 顯示性能顯著下降(p<0.05 的負變化),說明 DWARF5 安全性和兼容性良好。
總結
本次 Go1.25 新特性旨意,在 Go 編譯器使用 DWARF5,給 Go 應用程序的綜合多個方面帶來了不錯的提升,提升了 Go 在編譯和體積等原本強項上的更進一步提高。
這可能也是促進一些同學升級的契機之一。目前該提案已經合并到 master 分支并關閉該提案。
如無意外,我們將會在下一個新版本就可以享受到了。
參考資料
[1] cmd/compile: consider using DWARF 5: https://github.com/golang/go/issues/26379
[2] 基準測試結果: https://github.com/golang/go/issues/26379#issuecomment-2576441539