本页介绍了如何检查缓存命中率,以及如何在远程执行环境中调查缓存未命中问题。
本页面假定您有一个成功利用远程执行的 build 和/或测试,并且您希望确保有效利用远程缓存。
检查您的缓存命中率
在 Bazel 运行的标准输出中,查看列出了进程的 INFO
行,这些进程大致对应于 Bazel 操作。该行会详细说明执行操作的位置。查找 remote
标签(表示远程执行的操作)、linux-sandbox
(表示在本地沙盒中执行的操作),以及其他执行策略的其他值。结果来自远程缓存的操作会显示为 remote cache hit
。
例如:
INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.
在此示例中,有 6 次远程缓存命中,2 次操作未命中缓存,并在远程执行。可以忽略 3 个内部部分。这通常是一些微小的内部操作,例如创建符号链接。此摘要中不包含本地缓存命中次数。如果您得到的进程数为 0(或低于预期),请依次运行 bazel clean
和 build/test 命令。
缓存命中问题排查
如果您未获得预期的缓存命中率,请执行以下操作:
确保重新运行同一构建/测试命令会生成缓存命中
运行您希望填充缓存的构建和/或测试。首次在特定堆栈上运行新构建时,可能不会出现远程缓存命中。在远程执行过程中,操作结果会存储在缓存中,并且后续运行应会提取这些结果。
运行
bazel clean
。此命令会清理您的本地缓存,让您可以调查远程缓存命中,而无需在本地缓存命中掩盖结果。(在同一台机器上)再次运行您要调查的构建和测试。
检查
INFO
行中的缓存命中率。如果您除了remote cache hit
和internal
之外没有看到任何进程,则表示您的缓存正在正确填充和访问。在这种情况下,请跳到下一部分。差异可能的原因是 build 中某些非封闭因素导致相应操作在两次运行中收到不同的操作键。如需查找这些操作,请执行以下操作:
a. 重新运行相关的构建或测试以获取执行日志:
bazel clean
bazel --optional-flags build //your:target --execution_log_compact_file=/tmp/exec1.log
b. 比较两次运行的执行日志。确保两个日志文件中的操作完全相同。 差异可让您了解运行之间发生的更改。请更新您的 build 以消除这些差异。
如果您能够解决缓存问题,并且现在重复运行会生成所有缓存命中,请跳到下一部分。
如果您的操作 ID 相同,但没有缓存命中,则表示您的配置中的某些因素阻止了缓存。请继续阅读本部分,检查是否存在常见问题。
检查执行日志中的所有操作是否将
cacheable
设置为 true。如果某个操作的执行日志中未显示cacheable
,则表示相应规则的BUILD
文件定义中可能包含no-cache
标记。查看执行日志中的mnemonic
和target_label
字段,以帮助确定操作的来源。如果操作相同且为
cacheable
,但没有缓存命中,则您的命令行可能包含--noremote_accept_cached
,这会停用 build 的缓存查找。如果难以找出实际命令行,请使用 Build Event Protocol 中的规范命令行,如下所示:
a. 将
--build_event_text_file=/tmp/bep.txt
添加到 Bazel 命令中,以获取日志的文本版本。b. 打开文本版本的日志,并使用
command_line_label: "canonical"
搜索structured_command_line
消息。展开后,系统会列出所有选项。c. 搜索
remote_accept_cached
并检查它是否设置为false
。d. 如果
remote_accept_cached
为false
,请确定它是在哪里被设置为false
:命令行还是 bazelrc 文件中。
确保跨机器缓存
在同一机器上按预期发生缓存命中后,在另一台机器上运行相同的构建/测试。如果您怀疑缓存未跨机器进行,请执行以下操作:
对 build 进行少量修改,以避免命中现有缓存。
在第一台机器上运行 build:
bazel clean
bazel ... build ... --execution_log_compact_file=/tmp/exec1.log
在第二台机器上运行 build,确保包含第 1 步中的修改:
bazel clean
bazel ... build ... --execution_log_compact_file=/tmp/exec2.log
比较两次运行的执行日志。如果日志不相同,请检查 build 配置是否存在差异,以及是否有来自主机环境的属性泄露到其中任一 build 中。
比较执行日志
执行日志包含在构建期间执行的操作记录。每条记录都描述了输入(不仅是文件,还包括命令行参数、环境变量等)和操作的输出。因此,检查日志可以了解重新执行操作的原因。
执行日志可以采用以下三种格式之一生成:紧凑 (--execution_log_compact_file
)、二进制 (--execution_log_binary_file
) 或 JSON (--execution_log_json_file
)。建议采用紧凑格式,因为它生成的文件要小得多,且运行时开销非常少。以下说明适用于任何格式。您还可以使用 //src/tools/execlog:converter
工具在它们之间进行转换。
如需比较两个构建的日志,并确认它们未按预期共享缓存命中,请执行以下操作:
从每个构建中获取执行日志,并将其存储为
/tmp/exec1.log
和/tmp/exec2.log
。下载 Bazel 源代码并构建
//src/tools/execlog:parser
工具:git clone https://github.com/bazelbuild/bazel.git cd bazel bazel build //src/tools/execlog:parser
使用
//src/tools/execlog:parser
工具将日志转换为人类可读的文本格式。在此格式中,第二个日志中的操作将按顺序与第一个日志中的顺序进行排序,从而使比较变得更加轻松。bazel-bin/src/tools/execlog/parser \ --log_path=/tmp/exec1.log \ --log_path=/tmp/exec2.log \ --output_path=/tmp/exec1.log.txt \ --output_path=/tmp/exec2.log.txt
使用您喜爱的文本来区分
/tmp/exec1.log.txt
和/tmp/exec2.log.txt
。