RFC-0247:在 Fuchsia 中啟用 LTO

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

在 Fuchsia 中,只針對 Clang 工具鍊產生的目標二進位檔啟用名為「連結時間最佳化 (LTO)」的編譯器功能,但非偵錯 (即發布) 建構中的核心除外。

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

摘要

我們建議在 Fuchsia 中啟用名為「連結時間最佳化」(LTO) 的編譯器功能,但僅適用於 Clang 工具鍊產生的目標二進位檔 (不包括非偵錯 (即發布) 建構中的核心)。我們不會在本 RFC 中提議在核心和 Rust 中啟用 LTO。

動機

LTO 可提升執行階段效能並縮減程式碼大小,但會增加建構時間。搭配下列項目使用時,LTO 是邁向效能更高且更安全系統的墊腳石:

將 LTO 與 PGO 結合使用通常可獲得更優異的執行階段效能,因為 LTO 可根據收集的設定檔做出導向決策。此外,LTO 可讓您使用稱為 CFI 的安全性緩解技術。在 Fuchsia 上啟用 LTO 和 CFI,有助於與 Android 和 ChromeOS 等其他 OS 供應商達成功能對等。

利害關係人

協助人員:

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,可分別將智慧螢幕和 core_size_limits.arm64 的程式碼總大小減少 0.17 MiB 和 0.24 MiB。

  • 效能優勢:我們在 CQ 中執行效能建構工具,測量 LTO 的效能優勢。在智慧螢幕測試中,有 405 項測試的 LTO 獲得改善,其中部分測試的改善幅度超過 10%。此外,在平台建構工具中,LTO 改善了 5,226 項測試中的 1,959 項。我們也發現平台建構工具的效能大幅提升,部分甚至超過 30%。

回溯相容性

不必擔心回溯相容性問題。

安全性考量

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

隱私權注意事項

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

測試

我們計畫在 ToT 上預設啟用 LTO 後,依賴自動測試並標記任何功能或效能問題。

說明文件

LTO 必須新增至 Fuchsia 版本資訊。

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

編譯器在編譯個別模組時,最佳化機會有限,而 LTO 會在連結時執行最佳化,將最佳化範圍擴展至整個程式。這會增加連結時間,透過全程式分析和跨模組最佳化,提升執行階段效能。缺點是 LTO 會將更多建構成本轉移至連結時間,導致連結成本增加,且無法充分發揮平行處理和快取功能。

缺點:建構時間增加

啟用 LTO 會增加 CI/CQ 發行版本和開發人員建構版本的建構時間。我們在 CQ 中套用這個 CL,並測量對建構清理的影響,結果如下 (以 MM:SS 格式表示)。

CQ Builder RBE No 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 時,開發人員建構時間對建構僅限核心的 x64-release 設定完整清除建構作業的影響。

RBE No 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 No LTO LTO 時間變更
沒有 RBE/Goma 0:43 1:13 +0:30
RBE 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 和 Unified LTO

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

先前技術和參考資料

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

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

聯邦選舉委員會的裁決

Fuchsia 工程委員會 (FEC) 已投票通過接受這項 RFC,但附帶一些注意事項。

首先,FEC 同意 LTO 代表我們向合作夥伴 (然後是向使用者) 運送的二進位檔,朝正確方向邁出一步,原因如 gulfem@google.com 和 phosek@google.com 在 RFC 文字和留言串中提出的所有理由。

其次,FEC 承認這項異動的影響尚不確定。 為發布版本啟用 LTO 會對利害關係人造成正面和負面影響:使用者可享有更優異的效能;平台開發人員會發現更難對最佳化程式碼進行偵錯;開發人員和產品負責人可享有更小的二進位檔大小,尤其是在儲存空間受限的裝置上;平台開發人員會發現建構時間變長;基礎架構會在編譯上花費更多 CPU 週期,但在測試執行上花費的週期較少等。沒有人能預測完整影響,即使有人能預測,合理的利害關係人也可能不同意整體影響是正面。鑑於這種不確定性,我們認為 Toolchain 團隊已盡到應盡的責任。

變更生效後,如果利害關係人認為自己受到過度負面影響,建議向 Toolchain 團隊提出疑慮,如果疑慮未獲解決,則可向 FEC 提出申訴。如有新證據,我們隨時可以重新評估這項裁決。

最後,我們想特別向一組受到負面影響的利害關係人致歉:在核心以外,以發布模式建構的 C++ 平台開發人員,這是他們正常開發工作流程的一部分。這項變更很可能會大幅減緩遞增建構時間。雖然很遺憾,但我們認為啟用 LTO 仍是正確的選擇。

不過,這確實指出我們也認同的更大疑慮:隨著我們在更多程式碼集推出更智慧的最佳化工具,受影響的開發人員組合將會增加,而速度減緩的程度也會提高。開發人員不太可能確切知道建構作業變慢的原因,甚至可能不會意識到速度變慢,但工作效率仍會受到影響。

為避免這種情況,我們呼籲暫緩進行會增加建構時間的工具鍊相關變更,直到我們能將這些變更套用至發布的構件,且不會對團隊中大量開發人員造成影響為止 (請注意,團隊中大量開發人員無法使用偵錯建構版本)。舉例來說,我們可以將目前的兩種主要編譯模式 (偵錯和發布) 變成三種 (或許會反映 Bazel 的「偵錯、最佳化和快速建構」編譯模式),藉此解除進一步變更的封鎖。只有在其中一種模式下,才會執行耗費資源的最佳化作業,而其他兩種模式則可涵蓋絕大多數開發人員的使用情境。舉例來說,記錄一組特定的低階編譯器標記,供個別開發人員選擇採用,這樣是不夠的,因為這些個別標記組難以發現、缺乏建構工具涵蓋範圍,且快取命中率不佳。