動態執行

回報問題 查看來源

「動態執行」是 Bazel 中的功能,系統會利用第一個分支版本的輸出內容,從第一個分支版本的輸出內容取消另一個分支版本,同時啟動該動作的本機和遠端執行功能。它結合了遠端建構系統的執行能力和/或大型共用快取與本機執行作業的低延遲特性,可提供兩者最佳的環境優勢,讓您輕鬆建構乾淨和漸進式的建構作業。

本頁面說明如何啟用、調整動態執行功能及進行偵錯。如果您同時設定了本機和遠端執行作業,且想要調整 Bazel 設定以提升效能,請參閱本頁內容。如果您尚未設定遠端執行,請先參閱 Bazel 遠端執行總覽

要啟用動態執行功能嗎?

動態執行模組是 Bazel 的一部分,但為了利用動態執行,您必須已經能夠透過相同的 Bazel 設定在本機和遠端編譯。

如要啟用動態執行模組,請將 --internal_spawn_scheduler 標記傳遞至 Bazel。這會新增名為 dynamic 的新執行策略。您現在可以使用此方法做為要動態執行的記憶指令 (例如 --strategy=Javac=dynamic) 策略。請參閱下一節,瞭解如何選擇要啟用動態執行的記憶功能。

針對使用動態策略的任何記憶,遠端執行策略取自 --dynamic_remote_strategy 旗標和來自 --dynamic_local_strategy 標記的本機策略。傳送 --dynamic_local_strategy=worker,sandboxed 會設定動態執行作業本機分支版本的預設值,以便按照該順序試用工作站或沙箱執行作業。傳遞 --dynamic_local_strategy=Javac=worker 會覆寫 Javac 助聽器的預設值。遠端版本的運作方式相同。您可以多次指定這兩個標記。如果動作無法在本機執行,則會照常從遠端執行,反之亦然。

如果遠端系統有快取,--dynamic_local_execution_delay 旗標會在遠端系統表示快取命中後,將延遲時間 (以毫秒為單位) 新增至本機執行作業。避免在可能產生更多快取命中時執行本機執行作業。預設值為 1000 毫秒,但應該改為設定比快取命中時間更久一些。實際時間取決於遠端系統和往返時間。通常,指定遠端系統的所有使用者值都相同,除非其中部分使用者的距離足以增加往返延遲時間。您可以使用 Bazel 剖析功能,查看一般快取命中的花費時間。

動態執行功能可與本機沙箱策略搭配使用,也可與永久工作站搭配使用。永久工作站與動態執行搭配使用時,會自動以沙箱機制執行,且無法使用多工工作站。Darwin 和 Windows 系統的沙箱策略可能比較慢;您可以傳遞 --reuse_sandbox_directories,減少在這些系統上建立沙箱的負擔。

動態執行也可以透過 standalone 策略執行,但由於 standalone 策略必須在執行時採用輸出鎖定,因此可以有效阻止遠端策略結束執行。--experimental_local_lockfree_output 旗標的作用是解決這個問題,可讓本機執行作業直接寫入輸出內容,但這樣在先完成遠端執行作業時,便能取消這個作業。

如果動態執行作業的其中一個分支先完成,但發生錯誤,整個動作就會失敗。這是刻意的選擇,防止本機和遠端執行之間的差異。

如要進一步瞭解動態執行和鎖定的運作方式,請參閱 Julio Merino 的優質網誌文章

何時該使用動態執行?

動態執行需要某種形式的遠端執行系統。您目前無法使用純快取的遠端系統,因為快取失敗會視為失敗的動作。

並非所有動作類型都適合遠端執行。最理想的候選項目是在本機使用永久工作站且運作速度快,或是遠端執行負擔夠快的執行時間。由於每個本機執行的動作會鎖定一些 CPU 和記憶體資源,因此不符合這些類別的動作只會延遲執行。

自版本 5.0.0-pre.20210708.4 起,「效能剖析」包含工作站執行作業的相關資料,包括在關閉動態執行競賽後,完成工作要求所花費的時間。如果您看到動態執行工作站執行緒花費大量時間獲取資源,或是在 async-worker-finish 中有很長時間,表示本機動作可能會延遲工作站執行緒的執行速度變慢。

剖析動態執行效能不佳的資料

在上述使用 8 個 Javac 工作站的設定檔中,我們發現許多 Javac 工作站在 async-worker-finish 執行緒上失去競賽,並且完成工作。這是因為非工作站記憶力花費足夠資源延遲工作站。

以更優異的動態執行效能來剖析資料

如果只有 Javac 是以動態執行執行,則只有約一半的工作站在開始工作後最終會失去競賽。

先前建議的 --experimental_spawn_scheduler 旗標已淘汰。它會開啟動態執行功能,並將 dynamic 設為所有記憶方法的預設策略,這樣通常會導致這類問題。

效能

動態執行方式會假設本機有足夠的資源,而且遠端,值得投入一些額外資源來改善整體效能。但過度使用資源可能會導致 Bazel 本身或其執行機器的速度變慢,或在遠端系統上承受意外壓力。您可以透過以下其中一種方式變更動態執行的行為:

--dynamic_local_execution_delay 會在遠端分支版本啟動後,將本機分支版本的啟動延遲時間延遲數毫秒,但前提是在目前的建構作業期間曾發生遠端快取命中。這樣當建構作業有機會在快取中找到大部分的輸出內容時,就能受益於遠端快取,而不會浪費本機資源。視快取品質而定,減少這樣或許能改善建構速度,但代價會增加使用更多本機資源。

--experimental_dynamic_local_load_factor 是實驗性的進階資源管理選項。假如值介於 0 到 1 之間,就會關閉這項功能。 值設為大於 0 時,Bazel 會在多項等待排定動作時,調整本機排定的動作數量。如果設為 1,您可以安排多項動作,因為有可用的 CPU (如 --local_cpu_resources 一樣)。值越低,排定的動作數量就應越少,因為可執行的動作數量越多。這聽起來可能不符合直覺,但有了良好的遠端系統,本機執行在執行許多動作時無法帶來許多助益,而本機 CPU 則比較適合管理遠端動作。

如果遠端分支版本已至少執行這麼長的時間,--experimental_dynamic_slow_remote_time 會優先考慮啟動本機分支版本。由於最有機會贏得競賽,系統通常會優先採取最近期排定的動作,但如果遠端系統有時停止運作或需要較長時間,可能會導致建構繼續進行。這個選項預設為停用,因為這樣可能會隱藏想要修正的遠端系統問題。如果啟用這個選項,請務必監控遠端系統效能。

--experimental_dynamic_ignore_local_signals 可用來讓遠端分支版本因特定訊號而在本機產生退出時接管。這項功能主要搭配工作站資源限制 (請參閱 --experimental_worker_memory_limit_mb--experimental_worker_sandbox_hardening--experimental_sandbox_memory_limit_mb) 使用,其中工作站程序在使用過多資源時可能會終止。

JSON 追蹤記錄設定檔包含一些效能相關圖表,可協助您找出改善效能和資源用量的方法。

疑難排解

動態執行的問題可能難以偵錯,也難以偵錯,因為這類問題只能觸發本機和遠端執行作業的特定組合。--debug_spawn_scheduler 會從動態執行系統新增額外輸出內容,協助對這些問題進行偵錯。您也可以調整 --dynamic_local_execution_delay 旗標,以及遠端和本機工作的數量,以便更輕鬆地重現問題。

如果您在使用 standalone 策略進行動態執行時遇到問題,請嘗試在不使用 --experimental_local_lockfree_output 的情況下執行,或在沙箱環境中執行本機動作。這可能會減慢建構速度 (如果您使用 Mac 或 Windows,請參閱上述說明),但會移除部分可能失敗的原因。