本頁面說明如何使用永久工作站、優點、要求及 瞭解工作站對沙箱的影響。
永久工作站是 Bazel 伺服器啟動的長時間執行程序,
函式做為實際工具 (通常是編譯器) 的包裝函式,或者
工具本身。為了受益於持續性工作站,工具必須
支援執行一系列編譯,且包裝函式必須
工具 API 和下述的要求/回應格式之間。維持不變
系統在呼叫 worker 時,可能會使用及不使用 --persistent_worker
旗標的
而且負責以適當方式開始與
以及在結束時關閉 worker每個工作站執行個體都會獲派
(並非獨立的工作目錄)
<outputBase>/bazel-workers
。
使用永久工作站 執行策略, 啟動負擔、增加 JIT 編譯,並啟用快取 範例。這項策略 因此,只要將多個要求傳送至長時間執行, 上傳資料集之後,您可以運用 AutoML 自動完成部分資料準備工作
永久工作站適用於多種語言,包括 Java、 Scala、 Kotlin 等等。
使用 NodeJS 執行階段的程式可使用 @bazel/worker 輔助程式庫 實作工作站通訊協定
使用永久工作站
Bazel 0.27 以上版本
執行建構作業時預設會使用永久工作站,不過在執行建構作業時
優先順序較高。針對不支援永久工作站的動作,
Bazel 會改回為每個動作啟動工具執行個體。您可以特別提出
將 worker
設為使用永久工作站,藉此將版本設為使用永久工作站
策略
助憶鍵最佳做法是將 local
指定為
回 worker
策略:
bazel build //my:target --strategy=Javac=worker,local
使用 worker 策略取代本機策略,可提高編譯速度 速度會明顯變快,視導入方式而定Java 的建構作業可介於 2 至 4 之間 增加 1 倍,有時更多的漸進式編譯。編譯 Bazel 是 速度幾乎是工作人員的 2.5 倍詳情請參閱 「選擇工作站數量」專區。
您是否有與本機版本相符的遠端建構環境
您可以使用
動態策略,
它會影響遠端執行和工作站執行作業。如要啟用動態參數
就必須傳遞
--experimental_spawn_scheduler
旗標。這項策略會自動啟用 worker,因此您無需
指定 worker
策略,但仍可將 local
或 sandboxed
做為
候補。
選擇工作站數量
每記憶體的工作站執行個體預設數量為 4 個,但可以調整
使用
worker_max_instances
敬上
旗標。兩者之間有何權衡取捨
並獲得 JIT 編譯和快取命中的數量。員工人數越多,就可獲得更多
目標將支付執行非 JIT 程式碼的啟動成本,以及冷到
快取。如果您要建構的目標數量不多,單一工作站可能會提供
在編譯速度和資源用量之間取得最佳取捨 (例如
請參閱問題 #8586。
worker_max_instances
旗標會設定每個專案的工作站執行個體數量上限
助憶鍵和旗幟 (請見下方) 因此,在混合的系統中,您最終可以使用
會大量記憶體。如果是漸進式建構作業
使用多個工作站執行個體
就能享有更小的優勢
此圖表顯示 Bazel (目標) 的從頭編譯時間
//src:bazel
) (位於 6 核心超執行緒 Intel Xeon 3.5 GHz Linux 工作站)
搭載 64 GB RAM針對每個工作站設定,系統會執行五項簡潔建構作業,並
以及最後 4 格的平均分數
圖 1. 清理建構作業的效能改善圖表。
針對這項設定,兩個工作站的編譯速度最快,但只有 14% 與一個工作站相比。如果需要 減少記憶體用量
漸進式編譯通常能更完善。乾淨的建構作業 但在編譯之間變更單一檔案很常見, 特別是以測試導向開發上述範例也有一些非 Java 項目 並包裝動作來覆蓋漸進式編譯時間。
僅重新編譯 Java 來源
(//src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar
)。
但每次變更
AbstractContainerizingSandboxedSpawn.java
速度可達 3 倍 (平均有 20 個暖身版本,執行版本平均為 20 個漸進式版本)
已捨棄):
圖 2. 漸進式建構的效能改善圖表。
速度取決於變更。因此 6 的載入速度 是在上述常用常數發生變更時觸發。
修改永久工作站
您可以將
--worker_extra_flag
敬上
旗標,用於對工作站指定啟動標記,並以助憶鍵為索引鍵。舉例來說:
傳遞 --worker_extra_flag=javac=--debug
只會開啟 Javac 偵錯。
每次使用此標記時,只能設定一個工作站旗標,而且一次只能設定一個記憶式。
不僅可以為每個記憶式個別建立工作站,
初始化標記中的變化版本。每個助力和啟動的組合
標記會合併成一個 WorkerKey
,而每個 WorkerKey
最多不超過
可能會建立 worker_max_instances
個工作站。請參閱下一節,瞭解如何
動作設定也可以指定設定旗標
您可以使用
--high_priority_workers
敬上
標記,指定要按一般優先度優先執行的記憶法
助憶鍵這有助於優先處理最重要的關鍵動作
路徑。如果有兩個以上高優先順序的工作站正在執行要求,則所有
導致其他工作站無法執行這個標記可以重複使用。
傳送
--worker_sandboxing
敬上
標記時,每個 worker 要求都會針對其所有作業使用獨立的沙箱目錄
輸入內容設定沙箱需要一點時間,
尤其是在 macOS 上,但提供更好的正確性保證。
--worker_quit_after_build
敬上
標記主要用於偵錯和剖析這個標記會強制所有工作站
而不需要在建構完成後結束您也可以
--worker_verbose
到
取得更多 worker 作業相關資訊這個標記反映在
WorkRequest
中的 verbosity
欄位,可讓工作站實作
更詳細。
工作站會將記錄儲存在 <outputBase>/bazel-workers
目錄中,
例子
/tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log
。
檔案名稱包含工作站 ID 和記憶法。由於
每增加一次 WorkerKey
,你可能會看到超過 worker_max_instances
特定記憶的記錄檔
如需 Android 版本的詳細資訊,請參閱 Android「Build Performance」(Android 建構效能) 頁面。
實作永久工作站
詳情請參閱「建立永久工作站」頁面 瞭解如何設定工作站。
下方範例為使用 JSON 的工作站,顯示 Starlark 設定:
args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
ctx.actions.write(
output = args_file,
content = "\n".join(["-g", "-source", "1.5"] + ctx.files.srcs),
)
ctx.actions.run(
mnemonic = "SomeCompiler",
executable = "bin/some_compiler_wrapper",
inputs = inputs,
outputs = outputs,
arguments = [ "-max_mem=4G", "@%s" % args_file.path],
execution_requirements = {
"supports-workers" : "1", "requires-worker-protocol" : "json" }
)
根據這項定義,這項動作的第一步是從執行
指令列 /bin/some_compiler -max_mem=4G --persistent_worker
。要求
編譯 Foo.java
後看起來會像這樣:
注意:雖然通訊協定緩衝區規格使用的是「Snake case」(request_id
),
JSON 通訊協定會使用「駝峰式大小寫」(requestId
)。在本文件中,我們會使用
JSON 範例中的駝峰式大小寫,但在討論欄位時則使用蛇形大小寫
無論通訊協定為何
{
"arguments": [ "-g", "-source", "1.5", "Foo.java" ]
"inputs": [
{ "path": "symlinkfarm/input1", "digest": "d49a..." },
{ "path": "symlinkfarm/input2", "digest": "093d..." },
],
}
工作站會在 stdin
上以換行符號分隔的 JSON 格式收到此內容 (因為
requires-worker-protocol
設為 JSON)。worker 會執行動作
並將 JSON 格式的 WorkResponse
傳送至其 stdout 上的 Bazel。Bazel,然後
剖析此回應,然後手動將其轉換為 WorkResponse
proto。目的地:
使用二進位編碼的 protobuf 來與相關聯的工作站通訊
JSON,requires-worker-protocol
會設為 proto
,如下所示:
execution_requirements = {
"supports-workers" : "1" ,
"requires-worker-protocol" : "proto"
}
如果您沒有在執行要求中加入 requires-worker-protocol
,
Bazel 會將工作站通訊預設為使用 protobuf。
Bazel 會從助憶鍵和共用標記衍生出 WorkerKey
,因此如有
設定允許變更 max_mem
參數,其他工作站
。這可能會導致記憶體用量過大
使用太多變化。
每個工作站目前一次只能處理一項要求。實驗功能 多工工作站功能可讓您 執行緒,前提是基礎工具為多執行緒,且包裝函式設定為 瞭解這點
於 這個 GitHub 存放區 您可以看到使用 Java 和 Python 編寫的工作站包裝函式範例。如果發生以下情況: 是透過 JavaScript 或 TypeScript 運作 @bazel/worker 套件 和 nodejs 工作站範例 可能會有幫助
工作站對沙箱有何影響?
根據預設,使用 worker
策略不會在
沙箱,與 local
策略類似。您可以設定
--worker_sandboxing
標記,用於在沙箱內執行所有工作站,確保每個
執行此工具時,只會看見該工具應有的輸入檔案。工具
仍可能會在內部要求之間洩漏資訊,例如透過
快取。採用「dynamic
」策略
「工作站必須受到沙箱保護」。
為了讓工作站正確使用編譯器快取,系統會傳送摘要 為每個輸入檔案建立容器因此,編譯器或包裝函式可以檢查輸入 而無需讀取檔案。
即使使用輸入摘要來防止不需要的快取,沙箱機制仍然有效 工作人員提供的沙盒技術比純沙盒來得低,因為這項工具 可保留先前要求所影響的其他內部狀態。
只有在 worker 實作支援的情況下,才能啟用多重廣告工作站的沙箱機制,
而且,您必須透過
--experimental_worker_multiplex_sandboxing
標記。詳情請參閱
設計文件)。
延伸閱讀
如要進一步瞭解永久工作站,請參閱:
- 原始永久員工網誌文章
- Haskell 導入說明 {: .external}
- Mike Morearty 的網誌文章 {: .external}
- 使用 Bazel 進行前端開發:Angular/TypeScript 和永久工作站 w/ Asana {: .external}
- Bazel 策略說明 {: .external}
- 針對 bazel-discuss 的郵寄清單進行資訊豐富的員工策略討論 {: .external}