Fuchsia 專用的 Ninja 改善項目

Fuchsia 建構系統使用自訂 Ninja 二進位檔,可為開發人員體驗帶來多項改善。本頁面將說明這些項目。

提振精神

如要瞭解自訂 Fuchsia 專用 Ninja 的動機,請參閱 RFC-0153

簡而言之,上游版本難以提供許多功能,但這些功能對 Fuchsia 開發人員來說卻非常實用。

所有 Fuchsia 專屬變更都會在fuchsia-rfc-0153本機 Ninja Git 鏡像的分支版本上執行,並定期重新設定基準,方便以 GitHub 提取要求的形式傳送至上游專案,如 RFC 的「策略」一節所述。

功能:正在執行的指令狀態

將環境中的 NINJA_STATUS_MAX_COMMANDS 設為嚴格正整數,讓 Ninja 在智慧終端機中執行時,在狀態列下方列印執行時間最長的指令表格,以及這些指令的經過時間。舉例來說,使用 export NINJA_STATUS_MAX_COMMANDS=4 時,狀態可能如下所示:

[0/28477](260) STAMP host_x64/obj/tools/configc/configc_sdk_meta_generated_file.stamp
  0.4s | STAMP obj/sdk/zircon_sysroot_meta_verify.stamp
  0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...chsia.media/cpp/fuchsia.media_cpp_common.common_types.cc.o
  0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...fuchsia.media/cpp/fuchsia.media_cpp.natural_messaging.cc.o
  0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...dia/cpp/fuchsia.media_cpp_natural_types.natural_types.cc.o

以下動畫圖片顯示實際情況:

Ninja 多行狀態範例

請注意:

  • 在 Ninja 的試執行或詳細叫用中 (也就是使用 -n--verbose 標記),這項功能會自動停用。

  • 如果 Ninja 未在互動式 / 智慧終端機中執行,這項功能就會自動停用。

  • 執行控制台指令時,這項功能也會暫停 (如上例所示,執行 Bazel 動作時會暫停)。

  • 這項功能可讓您輕鬆找出建構作業的瓶頸,也就是長時間執行的指令,導致其他指令無法平行執行。

預設情況下,指令表每秒會更新 10 次,這有助於瞭解哪些長時間執行的指令會拖慢建構速度。您可以將 NINJA_STATUS_REFRESH_MILLIS 設為毫秒的十進位值,變更重新整理週期 (請注意,系統會忽略低於 100 的值,因為經過的時間只會列印到單一十進位分數位數)。

功能:支援 GNU Make Jobserver

GNU Make Jobserver 通訊協定可讓建構系統在任何時間點限制並行工作 (即執行緒或程序) 的總數,即使存在遞迴建構工具叫用也是如此。

這需要頂層 server 設定 job slots 集區,供參與的用戶端共用 (例如編譯器、連結器,甚至是建構工具)。

Fuchsia 專屬的 Ninja 二進位檔可做為通訊協定的用戶端或伺服器。

啟動 Ninja 時,您可以透過 --jobserver 指令列標記啟用伺服器模式,或在環境中設定 NINJA_JOBSERVER=1

啟動 Ninja 時,系統會查看 MAKEFLAGS 環境變數的值,自動啟用用戶端模式。如果 Ninja 是從做為伺服器的其他建構作業呼叫,這項功能就相當實用。

在 Fuchsia 建構作業中,於 args.gn 中設定 enable_jobserver = true,可讓頂層 Ninja 呼叫以伺服器模式啟動。

舉例來說,這項設定適用於核心 IDK 和核心 SDK 建構工具設定,可節省 6 到 12 分鐘的建構時間。因為這些作業需要從頂層建構作業啟動 24 個以上的 Ninja 子建構作業,而這些作業可運用通訊協定,更妥善地協調各自產生多個平行指令的方式。

功能:以 Chrome Trace JSON 陣列格式產生建構追蹤記錄

--chrome_trace FILENAME 選項可用於告知 Ninja 在建構作業完成後 (即使失敗也一樣),產生建構事件的追蹤記錄。

建議在輸出 FILENAME 中使用 .gz 後置字元,直接產生經過 gzip 壓縮的追蹤記錄檔,因為這類檔案通常會小 20 倍。

這個檔案採用 Chrome 追蹤 JSON 陣列格式,可直接載入任何 Chromium 架構瀏覽器的 chrome://tracing 分頁,更有趣的是,https://ui.perfetto.dev 也支援讀取壓縮追蹤記錄做為輸入內容。

請注意,產生的追蹤記錄檔也包含流程事件,有助於顯示建構作業的重要路徑。相應的建構事件會在 cat 欄位的值中顯示 critical_path

功能:持續模式可縮短啟動時間

在環境中設定 NINJA_PERSISTENT_MODE=1,加快後續 Ninja 呼叫速度。這項功能會讓 Ninja 啟動背景伺服器程序,讀取建構資訊清單一次,然後在連續建構之間將建構圖保留在記憶體中。

請注意:

  • 這項功能應完全透明,且不應影響 Ninja 的其他行為。如果發現問題或差異,請透過 fuchsia-build-team@google.com告訴我們!

  • 系統會自動偵測輸入 .ninja 檔案的任何變更。在這種情況下,現有伺服器會關閉,並自動啟動新伺服器。變更 GN 建構檔案或執行 jiri update 後,不需要額外與使用者互動。

  • 伺服器程序閒置 5 分鐘後,就會按適當流程關機。在環境中設定 NINJA_PERSISTENT_TIMEOUT_SECONDS=<count> 即可變更這項延遲。

  • 使用 fx build -t server status 擷取目前建構目錄的伺服器狀態。

  • 使用 fx build -t server stop 明確停止任何正在執行的伺服器執行個體。

  • NINJA_PERSISTENT_LOG_FILE=<path> 設為將與持續模式相關的記錄檔傳送至指定檔案路徑。

  • 目前,每個伺服器程序會為 core.x64 建構設定佔用約 1 GiB 的 RAM。確切數字取決於 Ninja 圖形的大小,而這又取決於您的 args.gn 設定。

  • 每個 Ninja 建構目錄最多只能由一個伺服器程序提供服務。 但使用多個建構目錄時,可能會有多個程序。

  • Ninja 工具 (例如 ninja -C <dir> -t commands <target>) 尚未在伺服器上執行,因此仍會使用緩慢的啟動程序。我們將在日後修正這個問題,加快查詢速度。

已知錯誤 / 注意事項 (將會解決):

  • 在同一目錄中混合使用持續性和非持續性建構作業,目前可能會造成伺服器混淆,因為系統無法正確偵測 Ninja 建構作業和依附元件記錄的獨立變更。我們會修正這個問題。

    解決方法:先使用 -t server stop 停止伺服器,再取消環境中的 NINJA_PERSISTENT_MODE 設定。

  • 「快速啟動」只需要幾秒鐘。目前,每個增量建構作業仍需為建構圖中的所有檔案呼叫 stat(),這目前需要幾秒鐘的時間。未來會使用主機作業系統的 inotify / kqueue 檔案系統監控功能修正這個問題,這樣一來,即使只有少數檔案經過修改,也能立即啟動。

  • 目前不支援 Windows。這是因為 Win32 的技術限制,導致無法將控制台控制代碼複製到其他程序。這主要是上游 Ninja 團隊的問題,因為 Fuchsia 開發作業並非在 Windows 上進行。