RFC-0247:在 Fuchsia 中啟用 LTO | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 在 Fuchsia 中,只針對由 Clang 工具鍊產生的目標二進位檔啟用名為「連結時間最佳化」(LTO) 的編譯器功能,但非偵錯 (即發布版本) 版本中的核心除外。 |
問題 | |
更小鳥 | |
作者 | |
審查人員 | |
提交日期 (年月分) | 2024-03-29 |
審查日期 (年-月-日) | 2024-05-02 |
摘要
我們建議只在 Fuchsia 中針對 Clang 工具鍊產生的目標二進位檔啟用名為連結時間最佳化 (LTO) 的編譯器功能,但非偵錯 (即發布版本) 建構作業中的核心除外。在此 RFC 中,我們不建議在核心和 Rust 中啟用 LTO。
動機
LTO 可提高執行階段效能,並縮減程式碼大小,但會增加建構時間。LTO 是為了實現效能更佳且更安全的系統,同時於下列情況下使用:
一般來說,將 LTO 與 PGO 結合在一起,通常會獲得更出色的執行階段效能,因為 LTO 可根據收集到的設定檔做出引導決策。此外,LTO 還能使用名為 CFI 的安全緩解技術。在 Fuchsia 上啟用 LTO 和 CFI 有助於與其他 OS 廠商 (例如 Android 和 ChromeOS) 的功能一致。
相關人員
講師:
hjfreyer@google.com
審查者:
- aaronwood@google.com
- olivernewman@google.com
- phosek@google.com
諮詢時間:
- awolter@google.com
- davidroth@google.com
- fmeawad@google.com
- mseaborn@google.com
社會化:
我們與 EngProd、Performance、Release、Software Assembly、Toolchain 和 Zircon Kernel 團隊與大家分享這個 RFC 的版本。
設計
我們開發了 CL,以便在非偵錯 (也稱為發布版本) 版本中預設啟用 LTO。我們只需要在後續的 CL 中開啟此功能。開發人員可以使用 GN 引數完全停用 LTO,減輕建構時間的影響。
導入方法
我們在這個 RFC 中實作提案,並達成必要的變更。
效能
LTO 提供規模和效能方面的優勢:
大小優勢:我們會在 CQ 中執行大小檢查工具建構工具,評估 LTO 的大小優勢,並發現只在 Clang 產生的二進位檔中啟用 LTO,將智慧型螢幕中的程式碼總大小減少 0.17 MiB,而在 core_size_limits.arm64 中則分別啟用 0.24 MiB。
效能優勢:我們在 CQ 中執行效能建構工具,以評估 LTO 的效能優勢。在 405 項智慧螢幕中,LTO 改善了 23 項測試 (共 405 項),其中我們看到各種提升幅度範圍超過 10%。此外,在 5,226 個平台建構工具中,LTO 改善了 1,959 項測試。我們也看到平台建構工具不僅效能大幅提升,其中部分效能也超過 30%。
回溯相容性
沒有回溯相容性的問題。
安全性考量
已透過 https://fxbug.dev/317396428 完成安全性審查。
隱私權注意事項
已透過 https://fxbug.dev/314790650 完成隱私權審查。
測試
一旦在 ToT 上預設啟用 LTO 並標記任何功能或效能問題,我們打算採用自動化測試。
說明文件
LTO 必須加入 Fuchsia 版本資訊。
缺點、替代方案和不明項目
缺點:連結時間增加
編譯器在編譯個別模組時,最佳化機會有限,且 LTO 會在連結期間執行最佳化作業,將最佳化範圍擴大到整個程式。透過整個程式分析和跨模組最佳化,這會增加連結時間,以改善執行階段效能。缺點是,LTO 將更多的建構成本與連結時間連結作業成本增加,並會降低平行處理和快取帶來的效益。
缺點:延長建構時間
啟用 LTO 會增加 CI/CQ 發布子版本和開發人員建構作業的建構時間。無論是否包含 RBE/Goma,我們都會套用這個 CL 值,藉此測量在 CQ 中對清理版本的影響,並以 MM:SS 格式回報從下方 ninja 步驟所花費的時間。
CQ 建構工具 | 盧比 | 沒有 LTO | LTO 授權 | 時間變化 |
---|---|---|---|---|
core_size_limits.x64-release | 無 RBE/Goma | 39:00 | 41:00 | +2:00 |
core_size_limits.x64-release | 盧比 | 6:00 | 8:18 | +2:18 |
Core.x64-release | 無 RBE/Goma | 66:00 | 66:00 | +0:00 |
Core.x64-release | 盧比 | 20:15 | 26:00 | +5:45 |
minimal.x64-release | 無 RBE/Goma | 72:00 | 78:00 | +6:00 |
minimal.x64-release | 盧比 | 17:48 | 25:00 | +7:12 |
Workbench_eng.x64-發布 | 無 RBE/Goma | 41:00 | 43:00 | +2:00 |
Workbench_eng.x64-發布 | 盧比 | 6:30 | 9:18 | +2:48 |
在下表中,我們透過執行 NINJA_STATUS=["%es] " fx build
,顯示開發人員建構時間對僅版本 Core.x64- 版本設定的完整乾淨建構作業影響。
盧比 | 沒有 LTO | LTO 授權 | 時間變化 |
---|---|---|---|
無 RBE/Goma | 26:48 | 27:15 | +0:27 |
RBE 冷快取 | 13:58 | 17:52 | +3:54 |
RBE 暖快取 | 13:55 | 15:53 | +1:58 |
我們測量了名為 driver_manager
的單一二進位檔的漸進式建構時間負擔。我們執行了下列步驟,評估 LTO 對完整建構管道的影響。
- 執行
fx build driver_manager
,執行簡潔式建構作業。 - 刪除這個來源檔案中的這一行。
- 執行漸進式建構作業,並透過
NINJA_STATUS=["%es] " fx build driver_manager
評估經過的時間。
我們會在下表中顯示 driver_manager
的漸進式建構時間負擔:
盧比 | 沒有 LTO | LTO 授權 | 時間變化 |
---|---|---|---|
無 RBE/Goma | 0:43 | 1:13 | +0:30 |
盧比 | 1:08 | 1:22 | +0:14 |
不明:顯示潛在問題
LTO 可能會因為跨模組執行最佳化作業,導致原始碼出現潛在問題,而這可能會導致已在使用中的某些假設失效,或顯示隱藏錯誤。
不明:對偵錯性的影響
另外也有一些疑慮,認為 LTO 對程式碼產生及偵錯的影響。雖然 LTO 通常對於偵錯能力應該沒有影響,而且我們尚未找出具體情況,但這仍然處於未知狀態。在提供這類情況後,我們就能調查編譯器偵錯資訊和偵錯工具與 LTO 互動是否不佳。
未來工作:在核心中啟用 LTO
我們計劃研究如何在核心中啟用 LTO 來評估其效益,並實驗將 LTO 與其他最佳化功能 (例如 PGO) 結合,然後再在核心中啟用 LTO。我們決定在使用者空間和核心中分別啟用 LTO 的優點,並禁止核心在這項 RFC 的涵蓋範圍內。
未來工作:在 Rust 中啟用 LTO
我們也計劃在 Rust 中啟用 LTO。初步結果顯示,在 Rust 中啟用 LTO 能進一步提高大小和效能。不過,我們決定採取階段式做法,在不同階段啟用 LTO,盡可能降低建構時間的影響和推出風險。
未來工作:啟用 FatLTO 和統一 LTO
我們計劃研究如何在 Fuchsia 中啟用 FatLTO 和 Unified LTO。不同的目標可能會有不同的建構時間和效能需求。舉例來說,將 LTO 套用至部分目標,但不適用於測試等其他目標,可能就非常實用。FatLTO 和 Unified LTO 可能有助於處理建構時間負擔與複雜度。不過,這些測試尚未準備好全面推出,並且需要一些偵錯和測試工作。
優先藝術與參考資料
Android 自 Android 9 起,已在核心和其他元件中啟用 LTO 和 CFI。Chrome 已部署 LTO、PGO 和 CFI。
我們目前在 Fuchsia 中廣泛使用 LTO,特別是 ffx 等 Fuchsia 開發中使用的大多數主機工具 (例如 ffx),而且預設使用 LTO 來改進這些工具的效能。此外,LTO 也扮演著重要的角色。
聯邦選舉委員會裁決
富士亞工程委員會 (FEC) 已投票接受這項 RFC,但有一些注意事項。
首先,FEC 同意 LTO 根據 RFC 文字和評論執行緒中由 gulfem@google.com 和 phosek@google.com 提出的所有二進位檔,代表我們將二進位檔提供給合作夥伴 (隨後再寄給使用者) 的一個步驟。
其次,FEC 承認這項異動的影響並不明確。 為發布子啟用 LTO 會對利害關係人帶來正面和負面的影響:使用者將受益於改善效能;平台開發人員會發現最佳化的程式碼更難偵錯;開發人員和產品擁有者將受益於較小的二進位檔,特別是在儲存空間限制有限的裝置上;平台開發人員將體驗更長的建構時間;平台開發人員將花更多的 CPU 週期,對編譯作業造成的負面影響,但會因為對於編譯執行結果的負荷程度減少,所以不會因為有人對編譯作業產生了負面影響,反而可能影響整體進行。有鑑於這種不確定性,我們認為工具鍊團隊已盡職調查。
相關異動生效後,我們會鼓勵所有認為自己受到過負面影響的利害關係人向工具鍊團隊提出疑慮,如果他們的疑慮並未獲得解決,再提報給 FEC。隨著新證據出現,我們隨時都可以重新評估此決定。
最後,我們要特別確認其中一名受到負面影響的利害關係人:在核心外,在核心開發期間建構的 C++ 平台開發人員做為正常開發工作流程的一部分。這項變更很可能會使漸進式建構速度明顯變慢。很遺憾,我們仍認為啟用 LTO 仍是正確的選擇。
不過,這確實有疑慮,而我們跟我們分享的是更廣泛的疑慮:隨著我們針對更多程式碼集推出更聰明的最佳化工具,受影響的開發人員數量會有所成長,速度變慢的程度也會增加。開發人員無法確切瞭解版本速度變慢的原因,甚至可能沒有意識到速度變慢,但生產速度仍會受損。
為了避免這種情況,我們要求提供其他工具鍊相關變更的 moratorium,直到我們可以將這些變更套用至我們推出的構件,同時不影響團隊中的大量開發人員 - 考量到團隊中的大量開發人員無法使用偵錯版本。舉例來說,我們可以將目前兩個主要的編譯模式 (偵錯和發布) 轉換成三種 (可能與 Bazel 的「debug、Opt and Fastbuild」編譯模式雙向同步),以排除進一步的變更。高成本最佳化只會在其中一種模式下執行,另外兩種模式則適用於絕大多數的開發人員用途。舉例而言,只記錄個別開發人員可選擇採用的特定低層級編譯器旗標組合並不足夠,因為這些個別標記將難以發現、建構工具涵蓋率不足,且快取命中率不佳。