优化迭代速度

报告问题 查看源代码 每夜 build · 8.0 · 7.4 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

Bazel 的运行时状态

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

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

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

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

  • Bazel 服务器也可以执行操作,或者可以发送操作以进行远程执行(如果已设置为执行此操作)。操作执行结果也会缓存,即在操作缓存(或执行缓存,该缓存可以是本地或远程缓存,并且可以供 Bazel 服务器共享)中。

  • Bazel 调用的结果会显示在输出树中。

迭代运行 Bazel

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

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

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

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

良好的执行缓存对构建性能也很有帮助。执行缓存可以存储在本地磁盘上,也可以存储在远程位置。缓存可在 Bazel 服务器之间共享,甚至在开发者之间共享。

避免舍弃分析缓存

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

  • 请注意在迭代工作流中途更改 bazel 标志。例如,将 bazel build -c optbazel cquery 混合使用会导致每个命令都舍弃对方的分析缓存。一般来说,请尝试在特定工作流的整个过程中使用一组固定的标志。

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

  • 注意,如果您在 Bazel 运行时重复按 Ctrl-C,则会终止 Bazel 服务器。您可能会尝试通过中断不再需要的正在运行的 build 来节省时间,但只需按 Ctrl-C 一次即可请求优雅地结束当前调用。

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