优化迭代速度

报告问题 查看源代码

本页面介绍如何在重复运行 Bazel 时优化 Bazel 的构建性能。

Bazel 的运行时状态

Bazel 调用涉及多个交互部分。

  • bazel 命令行界面 (CLI) 是面向用户的前端工具,用于接收来自用户的命令。

  • CLI 工具会为每个不同的输出基准启动一个 Bazel 服务器。Bazel 服务器通常是永久性的,但会在闲置一段时间后关闭,以免浪费资源。

  • Bazel 服务器会针对给定命令(buildruncquery 等)执行加载和分析步骤,在此过程中,它会在内存中构造构建图的必要部分。生成的数据结构将作为分析缓存的一部分保留在 Bazel 服务器中。

  • Bazel 服务器也可以执行操作,或者发送相关操作以便远程执行(如果已设置)。操作执行的结果也会缓存,即缓存在操作缓存(或执行缓存,可以是本地或远程的,并且可在 Bazel 服务器之间共享)。

  • Bazel 调用的结果将在输出树中提供。

以迭代方式运行 Bazel

在典型的开发者工作流中,开发者常常会重复构建(或运行)一段代码,而且频率通常非常高(例如,为了解决某些编译错误或调查失败的测试)。在这种情况下,对于 bazel 的重复调用,相对于底层的重复操作(例如调用编译器或执行测试)而言,其开销必须尽可能低。

有鉴于此,我们再来看一下 Bazel 的运行时状态:

分析缓存是关键数据。大量的时间只会花在冷运行的加载和分析阶段(即 Bazel 服务器启动之后的运行或分析缓存被舍弃时)。对于单次成功的冷构建(例如,生产版本),可承担这笔费用,但对于重复构建同一目标,必须摊销这笔费用,而不是在每次调用时重复。

分析缓存相当易失。首先,它是 Bazel 服务器的进程中状态的一部分,因此丢失服务器会使缓存丢失。不过,缓存也很容易失效:例如,许多 bazel 命令行标志都会导致缓存被舍弃。这是因为很多标志都会影响构建图(例如,由于可配置属性)。某些标志更改还可能会导致 Bazel 服务器重启(例如,更改启动选项)。

良好的执行缓存对构建性能也很重要。执行缓存可以保存在本地磁盘上,也可以远程保留。缓存可以共享给 Bazel 服务器,甚至可以在开发者之间共享。

避免舍弃分析缓存

如果分析缓存被舍弃或服务器重启,Bazel 会输出一条警告。在迭代使用过程中应避免以下两种情况:

  • 请注意在迭代工作流过程中更改 bazel 标志。例如,将 bazel build -c optbazel cquery 混用会导致每个命令舍弃彼此的分析缓存。通常,应尝试在特定工作流期间使用一组固定的标志。

  • 丢失 Bazel 服务器会导致分析缓存丢失。Bazel 服务器具有可配置的空闲时间,超过此时间后就会关闭。您可以通过 bazelrc 文件来配置此时间,以满足自己的需求。启动标志更改时,服务器也会重启,因此同样,请尽可能避免更改这些标志。

  • 请注意,如果在 Bazel 运行期间反复按 Ctrl-C,Bazel 服务器会终止。人们往往想尝试通过中断不再需要的正在运行的构建来节省时间,但只需按一次 Ctrl-C 即可请求顺利结束当前调用。

  • 如果要使用同一工作区中的多组标志,您可以使用通过 --output_base 标志切换的多个不同输出基准。每个输出库都有自己的 Bazel 服务器。

如需将此情况设为错误而非警告,您可以使用 --noallow_analysis_cache_discard 标志(在 Bazel 6.4.0 中引入)