2022 年 BazelCon 将于 11 月 16 日至 17 日在纽约和线上举办。
立即报名!

动态执行

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

动态执行是 Bazel 0.21 版中的一项功能,该功能使用同一个完成的分支的输出并行启动同一操作的本地和远程操作,从而取消另一个分支。它将远程构建系统的执行能力和/或大型共享缓存与本地执行的低延迟相结合,从而为干净构建和增量构建提供这两者的优势。

本页介绍了如何启用、调整和调试动态执行。如果您同时设置了本地执行和远程执行,并尝试调整 Bazel 设置以提高性能,那么本页面非常适合您。如果您尚未设置远程执行,请先转到 Bazel 远程执行概览

要启用动态执行吗?

动态执行模块是 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 助记符的默认值。远程版本的工作原理与此相同。您可以多次指定这两个标志。如果操作无法在本地执行,该操作会像往常一样远程执行,反之亦然。

如果您的远程系统有缓存,当远程系统指示缓存命中后,--experimental_local_execution_delay 标志会增加本地执行中的延迟(以毫秒为单位)。这样可以避免在可能存在更多缓存命中时运行本地执行。默认值是 1000 毫秒,但应调整为略快于缓存命中所用的时间。实际时间取决于远程系统和往返所需的时间。通常,对于某个远程系统,所有用户都将具有相同的值,除非其中一些用户距离足够远,从而增加往返延迟时间。您可以使用 Bazel 性能剖析功能来查看典型的缓存命中需要多长时间。

动态执行可与本地沙盒策略和永久性工作器结合使用。与动态执行功能配合使用时,永久性工作器将自动与沙盒化运行,并且不能使用多重工作器。在达尔文和 Windows 系统上,沙盒化策略可能很慢,您可以传递 --experimental_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 设置为所有助记符的默认策略,这通常会导致以下问题。

问题排查

动态执行的问题可能很细微且难以调试,因为它们可能仅在某些特定的本地和远程执行组合下出现。--experimental_debug_spawn_scheduler 添加了动态执行系统的额外输出,可帮助调试这些问题。您还可以调整 --experimental_local_execution_delay 标志以及远程与本地作业的数量,以便更轻松地重现问题。

如果您在使用 standalone 策略遇到动态执行问题,请尝试在不使用 --experimental_local_lockfree_output 的情况下运行,或者在沙盒中运行的本地操作。这可能会降低构建速度(如果您在 Mac 或 Windows 上,请参阅上文),但移除了一些可能的失败原因。