优化迭代速度

报告问题 查看来源 Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

本页介绍了在重复运行 Bazel 时如何优化 Bazel 的 build 性能。

Bazel 的运行时状态

Bazel 调用涉及多个相互作用的部分。

  • bazel 命令行界面 (CLI) 是面向用户的工具,可接收用户发出的命令。

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

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

  • Bazel 服务器还可以执行操作,或者在设置好后将操作发送到远程执行器。操作执行结果也会缓存起来,即缓存到操作缓存(或执行缓存,可以是本地缓存或远程缓存,并且可以在多个 Bazel 服务器之间共享)。

  • Bazel 调用的结果可在输出树中找到。

以迭代方式运行 Bazel

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

考虑到这一点,我们再来看看 Bazel 的运行时状态:

分析缓存是一项关键数据。在冷运行(即在 Bazel 服务器启动后或分析缓存被舍弃后立即运行)中,仅加载和分析阶段就可能花费大量时间。对于一次成功的冷构建(例如,针对正式版),此开销尚可承受,但对于重复构建同一目标,此开销必须分摊,而不是在每次调用时重复计算。

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

良好的执行缓存对于 build 性能也很有价值。执行缓存可以保存在本地磁盘上,也可以保存在远程。缓存可以在多个 Bazel 服务器之间共享,甚至可以在开发者之间共享。

避免舍弃分析缓存

如果分析缓存被舍弃或服务器重启,Bazel 将打印警告。在迭代使用期间,应避免使用以下任一方法:

  • 请注意,在迭代工作流程中途更改 bazel 标志可能会导致问题。例如,将 bazel build -c optbazel cquery 混合使用会导致每个命令舍弃另一个命令的分析缓存。一般来说,请尽量在特定工作流的整个持续时间内使用一组固定的标志。

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

  • 注意:如果在 Bazel 运行时反复按 Ctrl-C,Bazel 服务器会被终止。您可能会想通过中断不再需要的正在运行的 build 来节省时间,但请仅按一次 Ctrl-C 来请求正常结束当前调用。

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

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