動態執行

回報問題 查看來源

「動態執行」是 Bazel 中的功能,可在 Bazel 中平行執行相同動作的本機與遠端執行作業,並使用完成的第一個分支版本的輸出內容來取消其他分支版本。這項工具結合了遠端建構系統的執行效能和/或大量共用快取,以及本機執行極低延遲,因此能同時提供簡潔和漸進式建構作業的優勢。

本頁面說明如何啟用、調整及偵錯動態執行。如果您同時設定了本機和遠端執行作業,並嘗試調整 Bazel 設定以提升效能,那麼本頁面將派上用場。如果您尚未設定遠端執行,請先前往 Bazel Remote Execution 總覽

要啟用動態執行功能嗎?

動態執行模組屬於 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 則會關閉。 當值設為大於 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 使用者請參閱上方說明),但會移除一些可能失敗的原因。