多重工作站 (實驗功能)

回報問題 查看來源 Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

本頁說明多工工作站、如何編寫與多工相容的規則,以及特定限制的解決方法。

多工工作站可讓 Bazel 使用單一工作站程序處理多個要求。對於多執行緒工作站,Bazel 可以使用較少的資源,達到相同或更好的效能。舉例來說,Bazel 可以讓四個多工工作站與同一個工作站程序通訊,然後並行處理要求,而不必為每個工作站都建立一個工作站程序。對於 Java 和 Scala 等語言,這可節省 JVM 暖機時間和 JIT 編譯時間,一般來說,這也允許在相同類型的所有工作站之間使用一個共用快取。

總覽

Bazel 伺服器和工作站程序之間有兩層。對於可平行執行程序的特定助記符,Bazel 會從工作站集區取得 WorkerProxyWorkerProxy 會將要求連同 request_id 依序轉送至工作站程序,工作站程序會處理要求,並將回應傳送至 WorkerMultiplexer。當 WorkerMultiplexer 收到回應時,會剖析 request_id,然後將回應轉送回正確的 WorkerProxy。與非多工處理程序工作站一樣,所有通訊都是透過標準輸入/輸出完成,但工具無法只使用 stderr 做為使用者可見的輸出內容 (請參閱下文)。

每個工作人員都有一個金鑰。Bazel 會使用金鑰的雜湊碼 (由環境變數、執行根目錄和助記符組成),判斷要使用哪個 WorkerMultiplexer。如果 WorkerProxy 的雜湊碼相同,就會與同一個 WorkerMultiplexer 通訊。因此,假設單一 Bazel 叫用中的環境變數和執行根目錄相同,則每個不重複的助記符只能有一個 WorkerMultiplexer 和一個工作程序。工作站總數 (包括一般工作站和 WorkerProxy) 仍受 --worker_max_instances 限制。

編寫與多工相容的規則

規則的工作站程序應為多執行緒,才能充分運用多工工作站。即使串流中可能堆積多個要求,Protobuf 仍允許規則集剖析單一要求。工作站程序剖析串流中的要求時,應在新執行緒中處理要求。由於不同執行緒可能會同時完成並寫入串流,因此工作站程序必須確保回應是以不可分割的方式寫入 (訊息不會重疊)。回覆必須包含所處理要求的 request_id

處理多工輸出

多工處理工作者在處理輸出內容時,需要比單工處理工作者更加謹慎。傳送至 stderr 的所有內容都會寫入單一記錄檔,並在相同類型的所有 WorkerProxy 之間共用,且會隨機穿插在並行要求之間。雖然將 stdout 重新導向 stderr 是個好主意,但請勿將該輸出內容收集到 WorkResponseoutput 欄位,因為這可能會向使用者顯示經過處理的輸出內容。如果工具只會將以使用者為導向的輸出內容傳送至 stdoutstderr,您必須先變更該行為,才能啟用多工工作站。

啟用多工工作站

多工工作站預設為停用。規則集可以在動作的 execution_requirements 中使用 supports-multiplex-workers 標記,開啟多工工作站 (就像 supports-workers 標記啟用一般工作站一樣)。與使用一般工作者時相同,您需要指定工作者策略,無論是在規則集層級 (例如 --strategy=[some_mnemonic]=worker) 或一般策略層級 (例如 --dynamic_local_strategy=worker,standalone)。不需要額外標記,且如果同時設定 supports-multiplex-workerssupports-workers,則 supports-multiplex-workers 的優先順序較高。您可以傳遞 --noworker_multiplex,全面停用多工工作站。

建議規則集盡可能使用多工工作人員,以減輕記憶體壓力並提升效能。不過,除非實作多工沙箱,否則多工工作站目前不支援動態執行。嘗試使用動態執行功能執行非沙箱化多工工作者時,系統會改用沙箱化單工工作者,但不會顯示任何訊息。

多重廣告沙箱

您可以在工作站實作中明確新增多工支援,將多工工作站放入沙箱。單工工作站沙箱化可透過在各自的沙箱中執行每個工作站程序來完成,但多工工作站會在多個並行要求之間共用程序工作目錄。如要允許多工工作站進行沙箱化,工作站必須支援從每個要求中指定的子目錄讀取及寫入資料,而不是直接在工作目錄中進行。

為支援多工沙箱,工作站必須使用 WorkRequest 中的 sandbox_dir 欄位,並將其做為所有檔案讀取和寫入作業的前置字元。雖然 argumentsinputs 欄位與未經過沙箱處理的要求相同,但實際輸入內容與 sandbox_dir 相關。工作站必須翻譯 argumentsinputs 中的檔案路徑,才能從這個修改過的路徑讀取資料,且必須將所有輸出內容寫入 sandbox_dir 的相對路徑。包括「.」等路徑,以及引數中指定檔案的路徑 (例如 「argfile」 引數)。

工作站支援多工沙箱後,規則集即可在動作的 execution_requirements 中新增 supports-multiplex-sandboxing,宣告這項支援。如果傳遞 --experimental_worker_multiplex_sandboxing 標記,或工作站搭配動態執行使用,Bazel 就會使用多工沙箱。

沙箱化多工工作站的工作站檔案仍與工作站程序的運作目錄相關。因此,如果檔案同時用於執行工作站和做為輸入內容,則必須在 flagfile 引數和 toolsexecutablerunfiles 中指定為輸入內容。