本頁說明多工工作站、如何編寫多工相容規則,以及特定限制的解決方法。
多重工作站可讓 Bazel 透過單一工作站程序處理多個要求。針對多執行緒工作站,Bazel 可以使用較少的資源來達成相同目的,或是提升效能。例如,Bazel 不需要為每個工作站執行一個工作站程序,而是讓四個多工工作站與同一個工作站程序進行通訊,然後這些工作站會平行處理要求。針對 Java 和 Scala 等語言,這可以節省 JVM 暖機時間和 JIT 編譯時間,通常也允許所有相同類型工作站之間共用一個快取。
總覽
Bazel 伺服器和工作站程序之間有兩個層。針對可平行執行程序的特定記憶方法,Bazel 會從工作站集區取得 WorkerProxy
。WorkerProxy
會依序將要求和 request_id
轉送至工作站程序,工作站處理程序會處理要求,並將回應傳送至 WorkerMultiplexer
。WorkerMultiplexer
收到回應時,會剖析 request_id
,然後將回應轉送回正確的 WorkerProxy
。和非多工工作站一樣,所有通訊都會透過標準式內/流執行,但工具不能只使用 stderr
處理使用者可看到的輸出內容 (請見下方說明)。
每個工作站都有一個金鑰。Bazel 會使用金鑰的雜湊碼 (由環境變數、執行根目錄和記憶式程式碼組成) 來判斷要使用哪一個 WorkerMultiplexer
。如果 WorkerProxy
具有相同的雜湊碼,就會與相同的 WorkerMultiplexer
通訊。因此,假設在單一 Bazel 叫用中,環境變數和執行根目錄相同,則每個不重複的記憶都只能有一個 WorkerMultiplexer
和一個工作站程序。工作站總數 (包括一般工作站和 WorkerProxy
) 仍然受限於 --worker_max_instances
。
編寫多工相容規則
規則的工作站程序應採用多執行緒,以善用多工工作站。Protobuf 可讓規則集剖析單一要求,即使串流中可能有多個要求,也允許規則集剖析。每當工作站程序剖析串流中的要求時,應在新的執行緒中處理該要求。由於不同的執行緒可以同時完成並寫入串流,工作站程序需要確保回應是以不可分割的形式寫入 (訊息不會重疊)。回應必須包含其所處理要求的 request_id
。
處理多工輸出
相較於單一複雜工作站,Multix 工作站在處理輸出內容時需要更加謹慎。傳送到 stderr
的任何內容都會進入與所有相同類型 WorkerProxy
共用的單一記錄檔中,在並行要求之間隨機交錯。雖然將 stdout
重新導向至 stderr
是不錯的做法,但請勿將該輸出內容收集到 WorkResponse
的 output
欄位,因為這可能會向使用者顯示遮蓋的輸出內容。如果工具只會將使用者導向的輸出內容傳送至 stdout
或 stderr
,則需要先變更該行為,才能啟用多重工作站。
啟用 Multix 工作站
系統不會預設啟用多重工作站。規則集可以開啟多工工作站,方法是在動作的 execution_requirements
中使用 supports-multiplex-workers
標記 (如同 supports-workers
標記啟用一般工作站)。和使用一般工作站的情況一樣,您必須在規則集層級 (例如 --strategy=[some_mnemonic]=worker
) 或一般在策略層級 (例如 --dynamic_local_strategy=worker,standalone
) 指定工作站策略。不需要額外標記,且 supports-multiplex-workers
的優先順序高於 supports-workers
(如果兩者設定)。如要全面停用多工工作站,請傳遞 --noexperimental_worker_multiplex
。
建議盡可能使用多工工作站,以減少記憶體壓力並提高效能。不過,除非多 x 工作站實作多重沙箱,否則目前與動態執行不相容。如果嘗試在動態執行的情況下執行非採用沙箱機制的多工工作站,將會改為無通知地使用沙箱單一工作站。
多重沙箱
如要採用沙箱機制,可以在工作站實作中為多重工作站新增明確支援。雖然單面工作站沙箱可以透過各自的沙箱執行每個工作站程序來完成,但多 x 工作站會在多項平行要求之間共用處理程序工作目錄。如要允許多工工作站的沙箱作業,工作站必須支援讀取和寫入每個要求中指定的子目錄,而非直接在其工作目錄中讀取。
如要支援多工沙箱機制,工作站必須使用 WorkRequest
中的 sandbox_dir
欄位,並用該欄位做為所有檔案讀取和寫入的前置字串。雖然 arguments
和 inputs
欄位與未採用沙箱機制的要求保持不變,但實際輸入內容與 sandbox_dir
相關。工作站必須翻譯 arguments
和 inputs
中的檔案路徑,才能讀取這個修改過的路徑,而且也必須寫入以 sandbox_dir
為基礎的所有輸出。其中包括「.」等路徑,以及引數指定檔案中找到的路徑 (例如 "argfile" 引數)。
當工作站支援多工沙箱機制後,規則集就可以在動作的 execution_requirements
中新增 supports-multiplex-sandboxing
,以宣告此支援。如果傳遞 --experimental_worker_multiplex_sandboxing
標記,或工作站是與動態執行搭配使用,Bazel 就會使用多工沙箱機制。
採用沙箱機制的多工工作站檔案仍與工作站程序的工作目錄相關。因此,如果檔案同時用於執行工作站和輸入,則必須在標記檔案引數以及 tools
、executable
或 runfiles
中指定為輸入內容。