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(壓縮優(yōu)化)  | 在 v4 基礎上對   | 
Go 1.20+  | DWARF v4 + Zlib 壓縮(可選)  | 支持壓縮 DWARF 區(qū)段,縮小二進制體積,但仍為 v4。  | 
Go 1.22+  | DWARF v4 + 支持 position-independent DWARF  | 支持位置無關調試信息(如 DWARFv5 的一部分理念),但仍標注為 v4。  | 
DWARF5 背景和優(yōu)勢
現(xiàn)階段 DWARF5 還是比較新的輪子,于 2017 年發(fā)布。
在 DWARF5 的生態(tài)圈中,GNU 和 LLVM 工具鏈以及一些調試器都支持 DWARF5 。
GCC7.1(2017 年 5 月)和 GDB8.0(2017 年 6 月)中添加了支持大多數(shù) Xcode 工具也支持。因此作者關注到了他。
DWARF 一共有以下幾個正式版本:

原作者認為 DWARF5 與以前的 DWARF 版本相比,是具體以下幾個優(yōu)勢的:
- 支持位置無關的表示方式,這大大減少了目標文件中的重定位數(shù)量:
 
從而減小了目標文件的體積并減輕了鏈接器的負擔。
在 Go 可執(zhí)行文件中,503,361 個總重定位記錄中有 49% 來自 DWARF。
- 支持更為緊湊的位置與范圍列表格式:即便使用 zlib 壓縮,位置和范圍列表區(qū)段也僅占 12MiB Go 可執(zhí)行文件的 6%。
 - 為 Go 提供了官方的語言代碼。
 
基準測試結果
根據(jù)原作者提供的基準測試結果[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_*區(qū)段大幅簡化。 - 用戶態(tài)耗時有輕微優(yōu)化:
user-sec/op平均減少約 2.67%,表明在構建、鏈接等過程中均有輕微的優(yōu)化效果。 - 可執(zhí)行文件體積降低:可執(zhí)行文件總大小平均下降 3%,可視為 DWARF5 更緊湊的調試信息格式的直接成果。
 - 綜合無明顯退化表現(xiàn):沒有一個 benchmark 顯示性能顯著下降(p<0.05 的負變化),說明 DWARF5 安全性和兼容性良好。
 
總結
本次 Go1.25 新特性旨意,在 Go 編譯器使用 DWARF5,給 Go 應用程序的綜合多個方面帶來了不錯的提升,提升了 Go 在編譯和體積等原本強項上的更進一步提高。


這可能也是促進一些同學升級的契機之一。目前該提案已經(jīng)合并到 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















 
 
 











 
 
 
 