本頁說明多工工作站、如何編寫多 x 相容規則,以及有特定限制的解決方法。
多工工作站可讓 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
。
處理多重輸出內容
與單工工作站相比,多工工作站在處理輸出時必須格外謹慎。任何傳送至 stderr
的項目都會進入單一記錄檔,該檔案會與所有相同類型的 WorkerProxy
共用,並在並行要求之間隨機交錯。將 stdout
重新導向至 stderr
是不錯的做法,但請勿將輸出內容收集到 WorkResponse
的 output
欄位中,以免向使用者顯示雜亂的輸出內容。如果您的工具只會將使用者導向的輸出內容傳送至 stdout
或 stderr
,您必須先變更行為,才能啟用多工工作站。
啟用多 x 工作站
根據預設,系統不會啟用多重工作站。規則集可以在動作的 execution_requirements
中使用 supports-multiplex-workers
標記來開啟多工工作站 (就像 supports-workers
標記啟用一般工作站一樣)。就像使用一般工作站時,您必須在規則集層級 (例如 --strategy=[some_mnemonic]=worker
) 或通常在策略層級 (例如 --dynamic_local_strategy=worker,standalone
) 指定工作站策略。不需要任何額外標記,且如果同時設定兩者,系統會優先採用 supports-multiplex-workers
。supports-workers
您可以傳遞 --noworker_multiplex
,藉此在全球關閉多工工作站。
建議盡可能使用多 x 工作站,以降低記憶體壓力及改善效能。不過,除非多工工作站實作多 x 沙箱機制,否則目前與動態執行不相容。為了嘗試透過動態執行執行非採用沙箱機制的多工工作站,將改為使用採用沙箱機制的單複數工作站,而不顯示任何訊息。
多重廣告沙箱機制
您可以在工作站實作中明確支援多重工作站,藉此採用沙箱機制。雖然單個複雜工作站的沙箱機制可以在自己的沙箱中執行每個工作站程序,但多工工作站會在多個平行要求之間共用程序工作目錄。為了允許多 x 工作站使用沙箱機制,工作站必須支援讀取及寫入每個要求中指定的子目錄,而非工作目錄。
如要支援多工沙箱,工作站必須使用 WorkRequest
中的 sandbox_dir
欄位,並將該欄位做為所有檔案讀取和寫入作業的前置字串。雖然 arguments
和 inputs
欄位與未採用沙箱機制的要求相同,但實際輸入內容與 sandbox_dir
相關。工作站必須轉譯在 arguments
和 inputs
中找到的檔案路徑,才能從這個修改後的路徑讀取,而且也必須寫入相對於 sandbox_dir
的所有輸出內容。這包括「.」等路徑,以及在引數指定檔案中找到的路徑 (例如「argfile」引數)。
工作站支援多工沙箱後,規則集就可以將 supports-multiplex-sandboxing
新增至動作的 execution_requirements
,藉此宣告這項支援。如果傳遞 --experimental_worker_multiplex_sandboxing
旗標,或工作站與動態執行搭配使用,Bazel 就會使用多工沙箱機制。
採用沙箱機制的多 x 工作站的工作站檔案仍與工作站程序的工作目錄相對。因此,如果檔案同時用於執行 worker 做為輸入,就必須同時在旗標檔案引數中,以及 tools
、executable
或 runfiles
中將該檔案指定為輸入。