本页面介绍了如何检查缓存命中率,以及如何在远程执行上下文中调查缓存未命中。
本页面假定您的构建和/或测试能够成功利用远程执行,并且您希望确保自己有效地利用了远程缓存。
检查缓存命中率
在 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 时,应该不会有任何远程缓存命中。在远程执行过程中,操作结果会存储在缓存中,后续运行结果应该会提取这些结果。
运行
bazel clean
。此命令会清理您的本地缓存,这样一来,您便可以调查远程缓存命中,而结果不会被本地缓存命中遮盖。(在同一机器上)运行调查的 build 和测试。
请查看
INFO
行,了解缓存命中率。如果您看到除remote cache hit
和internal
以外的任何进程,则表明您的缓存已正确填充和访问。在这种情况下,请跳到下一部分。可能的差异来源是 build 中非封闭的内容,导致操作在两次运行中接收不同的操作键。如需找到这些操作,请执行以下操作:
a.重新运行相关 build 或测试以获取执行日志:
bazel clean
bazel --optional-flags build //your:target --execution_log_binary_file=/tmp/exec1.log
b. 在两次运行之间比较执行日志。确保两个日志文件中的操作完全相同。 通过差异,您可以了解两次运行之间的变化。请更新您的 build 以消除这些差异。
如果您能够解决缓存问题,并且现在重复运行会生成所有缓存命中,请跳到下一部分。
如果您的操作 ID 相同,但没有任何缓存命中,则表示配置中有某项内容阻止了缓存。继续完成此部分,检查是否存在常见问题。
如果您不需要区分执行日志,则可以改用直观易懂的
--execution_log_json_file
标志。它包含执行时间,并且不能保证顺序,因此无法用于稳定差异比较。检查执行日志中的所有操作是否均将
cacheable
设置为 true。如果指定操作的执行日志中未显示cacheable
,则表示相应规则在BUILD
文件的定义中可能有no-cache
标记。查看执行日志中直观易懂的progress_message
字段,以帮助确定操作的来源。如果操作相同且为
cacheable
但没有缓存命中,则您的命令行中可能包含针对 build 停用缓存查询的--noremote_accept_cached
。如果难以确定实际命令行,请使用 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 文件中。
确保可以跨机器进行缓存
在同一台计算机上按预期执行缓存命中后,在其他机器上运行相同的构建/测试。如果您怀疑缓存未在机器间运行,请执行以下操作:
对构建稍作修改,以避免命中现有缓存。
在第一台机器上运行构建:
bazel clean
bazel ... build ... --execution_log_binary_file=/tmp/exec1.log
在第二台机器上运行 build,确保包含第 1 步中所做的修改:
bazel clean
bazel ... build ... --execution_log_binary_file=/tmp/exec2.log
比较两次运行的执行日志。如果日志不相同,请调查构建配置是否存在差异,以及主机环境中是否存在泄露到任一 build 中的属性。
比较执行日志
执行日志包含构建期间执行的所有操作的记录。每个操作都有一个 SpawnExec 元素,其中包含操作键中的所有信息。因此,如果日志相同,则操作缓存键也相同。
如需比较两个未按预期共享缓存命中的构建的日志,请执行以下操作:
从每个 build 中获取执行日志,并将其存储为
/tmp/exec1.log
和/tmp/exec2.log
。下载 Bazel 源代码,然后使用以下命令导航到 Bazel 文件夹。您需要使用源代码来使用 execlog 解析器解析执行日志。
git clone https://github.com/bazelbuild/bazel.git cd bazel
使用执行日志解析器将日志转换为文本。以下调用还会对第二个日志中的操作进行排序,以匹配第一个日志中的操作顺序,以方便比较。
bazel build 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
。