动态执行是 Bazel 中的一项功能,可让系统在本地和远程执行 使用第一个分支的输出并行启动相同的操作 结束另一个分支。它结合了执行能力, 和/或远程构建系统的大型共享缓存 两全其美地进行干净和增量构建 等。
本页介绍了如何启用、调整和调试动态执行。如果您 已设置本地和远程执行,并正在尝试调整 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 助记符。遥控器版本的工作原理相同。两个标记都可以
指定多次。如果某个操作无法在本地执行,
远程执行,反之亦然。
如果远程系统有缓存,则 --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
,您可能会因为一些缓慢的本地操作而延迟 worker
线程。
在上面的配置文件(使用 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
会优先启动本地分支
当远程分支已运行了至少这么长的时间时触发。通常,
最近的预定操作的优先级较高,因为它最有可能
赢得比赛,但如果远程系统偶尔挂起或耗时过长,
这样就能让 build 继续推进。默认情况下,该功能并未启用
可能会掩盖远程系统的问题,而应该解决这些问题。请确保
监控远程系统性能(启用此选项)。
--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),但移除了一些可能导致故障的原因。