RFC-0247:在 Fuchsia 中啟用 LTO

RFC-0247:在 Fuchsia 中啟用 LTO
狀態已接受
區域
  • 建構
  • 工具鏈
說明

在 Fuchsia 中啟用名為「Link Time Optimization (LTO)」的編譯器功能,但僅適用於由 Clang 工具鍊產生的目標二進位檔,非偵錯 (又稱為發布) 版本的核心除外。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2024-03-29
審查日期 (年-月-日)2024-05-02

摘要

我們建議您只針對由 Clang 工具鍊產生的目標二進位檔 (非偵錯版本的核心除外),在 Fuchsia 中啟用名為「Link Time Optimization」(LTO) 的編譯器功能。我們不建議在本 RFC 中啟用核心和 Rust 中的 LTO。

動機

LTO 可改善執行階段效能並縮減程式碼大小,但會增加建構時間。LTO 與下列項目搭配使用,可協助您打造效能更高且安全性更高的系統:

LTO 和 PGO 通常可搭配使用,以便根據收集到的設定檔做出引導決策,進而提升執行階段效能。此外,LTO 還可讓您使用名為 CFI 的安全防護技術。在 Fuchsia 上啟用 LTO 和 CFI,有助於與 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

社會化:

我們已將此 RFC 的某個版本與 EngProd、Performance、Release、Software Assembly、Toolchain 和 Zircon Kernel 團隊分享。

設計

我們已推出 CL,以便在非偵錯 (又稱為發布) 版本中預設啟用 LTO。我們只需要在後續的 CL 中開啟這項功能。開發人員可以使用 GN 引數來完全停用 LTO,以減輕建構時間的影響。

導入

我們已實作此 RFC 中的提案,並完成必要的變更。

效能

LTO 可提供大小和效能方面的優勢:

  • 大小效益:我們在 CQ 中執行大小檢查器建構工具,以評估 LTO 的大小效益,結果發現只在 Clang 產生的二進位檔中啟用 LTO,可分別在智慧型螢幕中減少 0.17 MiB 的總程式碼大小,以及在 core_size_limits.arm64 中減少 0.24 MiB。

  • 效能優勢:我們在 CQ 中執行效能建構工具,以評估 LTO 的效能優勢。在智慧型螢幕的 405 項測試中,有 23 項測試因採用 LTO 而獲得改善,其中部分測試的效益超過 10%。此外,在平台建構工具中,有 5,226 項測試中有 1,959 項經過 LTO 改善。我們也發現平台建構工具的成效提升幅度相當大,其中有些甚至超過 30%。

回溯相容性

不必擔心回溯相容性。

安全性考量

安全性審查已透過 https://fxbug.dev/317396428 完成。

隱私權注意事項

我們已透過 https://fxbug.dev/314790650 完成隱私權審查。

測試

我們打算在 ToT 上預設啟用 LTO,並依據自動化測試標示任何功能或效能問題。

說明文件

LTO 需要加入 Fuchsia 版本資訊。

缺點、替代方案和未知事項

編譯器在編譯個別模組時,可進行的最佳化機會有限,而 LTO 會在連結期間執行最佳化,將最佳化範圍擴大至整個程式。這會增加連結時間,透過整個程式分析和跨模組最佳化,達成更佳的執行階段效能。缺點是,LTO 會將更多建構成本轉移至連結時間,連結成本會變得更高,並且無法充分發揮並行處理和快取的效益。

缺點:建構時間增加

啟用 LTO 會增加 CI/CQ 發布建構和開發人員建構的時間。我們在 CQ 中套用這個 CL,並在有/無 RBE/Goma 的情況下,測量建構時間對清理建構作業的影響,並以 MM:SS 格式回報下方的忍者步驟所需的時間。

CQ Builder RBE 不提供 LTO LTO 時間變更
core_size_limits.x64-release 無 RBE/Goma 39:00 41:00 +2:00
core_size_limits.x64-release RBE 6:00 8:18 +2:18
core.x64-release 無 RBE/Goma 66:00 66:00 +0:00
core.x64-release RBE 20:15 26:00 +5:45
minimal.x64-release 無 RBE/Goma 72:00 78:00 +6:00
minimal.x64-release RBE 17:48 25:00 +7:12
workbench_eng.x64-release 無 RBE/Goma 41:00 43:00 +2:00
workbench_eng.x64-release RBE 6:30 9:18 +2:48

在下表中,我們透過執行 NINJA_STATUS=["%es] " fx build,顯示開發人員在執行完整的清除建構作業時,對僅建構 core.x64-release 設定的建構時間影響。

RBE 不提供 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 的遞增式建構時間額外負擔:

RBE 不提供 LTO LTO 時間變更
無 RBE/Goma 0:43 1:13 +0:30
RBE 1:08 1:22 +0:14

不明:顯示潛在問題

LTO 可能會公開原始碼中的潛在問題,因為它會在各模組中執行最佳化作業,這可能會使現有的特定假設失效,或顯示隱藏的錯誤。

不明:對可偵錯性造成的影響

也有人對 LTO 對程式碼產生和偵錯的影響提出疑慮。雖然 LTO 一般來說不會影響偵錯功能,而且我們尚未找出具體案例,但這仍是未知數。在提供這類案例時,我們可以調查編譯器偵錯資訊和偵錯工具是否在特定情況下與 LTO 互動不良。

未來工作:在核心中啟用 LTO

我們打算在核心中啟用 LTO 來評估其效益,並在核心中啟用 LTO 前,實驗將 LTO 與 PGO 等其他最佳化技術結合。我們決定將在使用者空間啟用 LTO 與在核心啟用 LTO 的優點分開,並將核心排除在本 RFC 的範圍之外。

未來工作:在 Rust 中啟用 LTO

我們也打算在 Rust 中啟用 LTO。初步結果顯示,在 Rust 中啟用 LTO 可進一步改善大小和效能。不過,我們決定採用階段式做法,在不同階段啟用 LTO,以盡量降低建構時間影響和推出風險。

未來工作:啟用 FatLTO 和統一 LTO

我們預計會在 Fuchsia 中啟用 FatLTO 和統一 LTO。不同的目標可能有不同的建構時間和效能需求。舉例來說,將 LTO 套用至某些目標可能會有所助益,但其他目標 (例如測試) 則不適用。FatLTO 和 Unified LTO 可能有助於減少建構時間的額外負擔和複雜度。不過,這些功能尚未準備好全面推出,需要進行一些偵錯和測試工作。

先前技術和參考資料

自 Android 9 起,Android 在其核心和其他元件中啟用 LTO 和 CFI。Chrome 已部署 LTOPGOCFI

我們目前在 Fuchsia 中廣泛使用 LTO,特別是我們在 Fuchsia 開發中使用的大多數主機工具 (例如 ffx),預設會使用 LTO 建構,而 LTO 對於改善這些工具的效能至關重要。

聯邦選舉委員會的決定

Fuchsia Engineering Council (FEC) 已投票接受此 RFC,但附帶一些附帶條件。

首先,FEC 同意 LTO 是我們向合作夥伴 (然後向最終使用者) 發布的二進位檔正確的方向,因為 gulfem@google.com 和 phosek@google.com 在 RFC 文字和留言串中提出了所有理由。

第二,FEC 承認這項異動的影響尚不明朗。為發布版本啟用 LTO 會對利益相關者產生正面和負面影響:使用者可從效能提升中受益;平台開發人員會發現,最佳化程式碼更難進行偵錯;開發人員和產品擁有者可從較小的二進位檔大小中受益,尤其是在儲存空間受限的裝置上;平台開發人員的建構時間會拉長;基礎架構會在編譯時使用更多 CPU 週期,但在測試執行時使用較少 CPU 週期,等等。沒有人能預測完整的影響,即使有人能預測,合理的利益相關者也可能會對整體影響是否為正面產生分歧。考量到這種不確定性,我們認為工具鍊團隊已盡到審慎評估的責任。

變更生效後,如果有任何利害關係人認為自己受到過度負面影響,我們建議他們向工具鍊團隊提出疑慮,如果疑慮未獲得解決,則可提報給 FEC。我們隨時可以重新評估這項決定,並在有新證據時做出調整。

最後,我們想特別感謝一群受到負面影響的利害關係人:在核心外部以發布模式進行建構的 C++ 平台開發人員,他們將這項作業納入正常開發工作流程。這項變更很可能會大幅降低增量建構時間。雖然這很不幸,但我們認為啟用 LTO 仍是正確的選擇。

不過,這確實指出了更嚴重的問題,我們想與大家分享:隨著我們在更多程式碼庫中推出更聰明的最佳化工具,受影響的開發人員數量將會增加,而速度減緩的程度也會增加。開發人員可能無法確切知道為何版本產生速度變慢的情形,甚至可能不會察覺速度變慢,但他們的工作效率仍會受到影響。

為避免這種情況,我們要求暫停進行其他工具鍊相關變更,因為這些變更會增加建構時間,且我們必須在確保不會影響團隊中大量開發人員的情況下,才能將這些變更套用至我們發布的構件,因為團隊中大量開發人員無法使用偵錯版本。舉例來說,我們可以將目前的兩種主要編譯模式 (偵錯和發布) 擴充為三種 (或許會模擬 Bazel 的「偵錯、最佳化和快速建構」編譯模式),藉此解除進一步變更的封鎖。耗時的最佳化作業只會在其中一種模式下執行,而其他兩種模式則涵蓋絕大多數開發人員的用途。相反的例子是,記錄個別開發人員可選擇採用的特定低階編譯器標記,並不足以說明這些標記的用途,因為這些個別標記組合不易發現、缺乏建構工具涵蓋範圍,且快取命中率偏低。