使用任何构建缓存的唯一原因是加快构建速度。但是使用缓存能让构建快多少呢?衡量其影响既重要又复杂,因为缓存性能受多种因素决定。衡量缓存的影响可以验证开始使用缓存所需的额外努力(工作量、基础设施)是否值得。这些衡量结果后续可以作为未来改进的基线,并监测是否存在性能退步的迹象。

正确配置和维护构建可以大大提高缓存性能。

完全缓存构建

了解缓存能为你带来什么的最直接方法是测量非缓存构建与完全缓存构建之间的差异。这可以让你了解如果所有构建目标都已构建过,使用缓存的理论速度上限。最简单的衡量方法是使用本地缓存

  1. 清理缓存目录以避免先前构建的任何命中 (rm -rf $GRADLE_USER_HOME/caches/build-cache-*)

  2. 运行构建(例如 ./gradlew --build-cache clean assemble),以便所有可缓存任务的结果都存储在缓存中。

  3. 再次运行构建(例如 ./gradlew --build-cache clean assemble);根据你的构建,你应该会看到许多任务从缓存中检索。

  4. 比较两次构建的执行时间

即使在两次构建的第一次运行中,你可能也会遇到一些缓存任务,尽管此时应该没有任何先前缓存的结果可用。这可能发生在你的构建中配置的任务针对相同的输入产生相同的输出;在这种情况下,一旦其中一个任务完成,Gradle 将简单地重用其输出给其余任务。

通常,你的完全缓存构建应该比 clean 构建快得多:这是使用构建缓存可以在你的特定构建上节省多少时间的理论极限。通常第一次尝试无法获得可达到的性能提升,请参阅查找任务输出缓存问题。随着你的构建逻辑演变和改变,确保缓存效率没有下降也很重要。构建扫描提供了详细的性能分解,向你展示你的构建如何有效地使用构建缓存

performance task execution

完全缓存构建通常发生在开发者从版本控制中拉取最新代码然后进行构建的情况,例如生成他们在 IDE 中需要的最新源文件。然而,运行大多数构建的目的是处理一些新的更改。正在构建的软件结构(有多少模块,其各个部分有多独立等)以及更改本身的性质(例如“系统核心的大规模重构” vs “单元测试的小改动”)都会强烈影响构建缓存带来的性能提升。由于开发者倾向于随着时间提交不同类型的更改,缓存性能预计会随每次更改而变化。与任何缓存一样,因此应该随着时间来衡量其影响。

在团队使用共享缓存后端的情况下,有两个地方值得衡量缓存影响:在 CI 和在开发者机器上。

缓存对 CI 构建的影响

了解缓存对 CI 影响的最佳方法是分别设置启用和禁用缓存的相同构建,并随时间比较结果。如果你有一个想要启用缓存的单个 Gradle 构建步骤,使用 CI 系统内置的统计工具很容易比较结果。

衡量复杂的流水线可能需要更多工作或外部工具来收集和处理衡量数据。重要的是要区分流水线中缓存对其没有影响的部分,例如构建在 CI 系统队列中等待的时间,或从版本控制中检出源代码所花费的时间。

使用 Develocity 时,你可以使用导出 API 来访问必要的数据并运行分析。与从 CI 服务器获取的数据相比,Develocity 提供了更丰富的数据。例如,你可以深入了解单个任务的执行情况、从缓存中检索了多少任务、从缓存下载需要多长时间、用于计算缓存键的属性等等。使用 CI 服务器的内置功能时,如果你使用 Teamcity 进行 CI 构建,可以使用统计图表。大多数情况下,你最终会通过相应的 REST API 从 CI 服务器提取数据(参见Jenkins 远程访问 APITeamcity REST API)。

通常,达到一定规模的 CI 构建包含并行部分,以利用多个代理。通过并行流水线,你可以测量从一组更改被推送到版本控制到构建、验证和部署所需的实际时间。在这种情况下,构建缓存的影响可以通过减少开发者等待 CI 反馈的时间来衡量。

你还可以测量构建代理构建一个 changeset 所花费的累计时间,这将让你了解 CI 基础设施需要投入的工作量。缓存在此处的效果是减少 CI 资源的开销,因为你不需要那么多 CI 代理来维护相同数量的已构建更改。

如果你想查看 Gradle 构建本身的度量,可以看看博客文章“构建缓存介绍”

衡量开发者构建

Gradle 的构建缓存对于降低 CI 基础设施成本和缩短反馈时间非常有用,但当开发者可以在其本地构建中重用缓存结果时,其影响通常最大。由于多种原因,这也是最难量化的

  • 开发者运行不同的构建

  • 开发者可能有不同的硬件,或有不同的设置

  • 开发者在其机器上运行各种其他程序,这可能会减慢速度

使用 Develocity 时,你也可以使用导出 API 来提取有关开发者构建的数据。然后,你可以按开发者或构建创建关于有多少任务被缓存的统计信息。你甚至可以比较执行任务所需的时间与从缓存加载任务所需的时间,然后估算每个开发者节省的时间。

使用 Develocity 构建缓存后端 时,应密切关注管理 UI 中的命中率。命中率的上升可能表明开发者对其使用了更好。

build cache hit rate

在构建扫描中分析性能

构建扫描通过“性能”页面的“构建缓存”部分提供构建的所有缓存操作摘要。

build cache performance

此页面详细说明了哪些任务通过缓存命中得以跳过,哪些任务未命中。它还分别指出了本地缓存和远程缓存的命中和未命中情况。对于远程缓存操作,会给出向缓存传输或从缓存传输 Artifacts 所花费的时间以及传输速率。这对于评估网络连接质量对性能的影响尤为重要,因为传输时间会影响构建时间。

远程缓存性能

改善构建与远程缓存之间的网络连接可以显著提高构建缓存性能。具体如何操作取决于所使用的远程缓存和你的网络环境。

Develocity 提供的多节点远程构建缓存是一种快速高效、专用的远程构建缓存。特别是,如果你的开发团队地理位置分散,其复制功能可以通过允许开发者使用与其网络连接良好的缓存来显著提高性能。有关更多信息,请参阅 Develocity 管理手册的“构建缓存复制”部分