23、构建性能优化:并行执行、配置优化、避免不必要的任务、使用分析报告

说实话,Gradle 项目一大了,构建速度慢得让人抓狂。我见过不少团队,每天等构建的时间比写代码还多。嗯,这其实不是 Gradle 的问题,而是我们没把它调教好。

今天咱们就聊聊怎么让 Gradle 跑得更快。说白了就四个方向:并行干活、少做无用功、配置别太啰嗦、用报告找瓶颈。

核心思路:构建优化的本质是「减少工作量」+「提高并行度」。别想着一步到位,先找到最慢的环节。

一、并行执行:让 CPU 别闲着

Gradle 默认是串行执行任务的。你想想看,一个项目有几十个模块,每个模块都要编译、测试、打包,如果一个个来,CPU 大部分时间都在空转。

开启并行构建,只需要在 gradle.properties 里加一行:

org.gradle.parallel=true

我个人习惯还会设置并行线程数:

org.gradle.workers.max=4

这个数字一般设成 CPU 核心数减 1 比较稳妥。我在项目中遇到过,设成 8 反而更慢——因为线程切换开销太大了。

小技巧:如果你不确定设多少合适,可以先不设 workers.max,Gradle 会自动根据 CPU 核心数来分配。

另外,按模块并行也很重要。如果你的项目是多模块结构,记得加上:

org.gradle.caching=true

这样不同模块之间可以并行构建,互不干扰。

二、配置优化:别在配置阶段做太多事

Gradle 的构建分三个阶段:初始化、配置、执行。很多人把耗时操作写在了配置阶段,结果每次运行 gradle tasks 都要等半天。

配置阶段应该只做声明,不做计算。比如:

// ❌ 错误做法:配置阶段执行耗时操作
allprojects {
    task myTask {
        doLast {
            // 这里才真正执行
        }
    }
    // 这里不要写耗时逻辑
}

// ✅ 正确做法:用 doLast 或 doFirst 延迟执行
allprojects {
    task myTask {
        doLast {
            // 耗时操作放在这里
            Thread.sleep(1000)
        }
    }
}

我曾经见过一个项目,配置阶段要跑 30 秒——因为有人在里面调用了远程 API。嗯,这其实是个设计问题。

另一个常见坑:在配置阶段读取文件。比如:

// ❌ 每次配置都读文件
def config = new File('config.json').text

// ✅ 用 Provider 延迟读取
def config = providers.fileContents('config.json').asText

注意:配置阶段的代码每次运行 Gradle 都会执行,哪怕你只是看看有哪些任务。所以一定要轻量。

三、避免不必要的任务:少做就是快

Gradle 的增量构建机制已经很智能了,但有些场景还是需要我们手动干预。

1. 使用 up-to-date 检查

Gradle 默认会检查任务的输入输出是否变化。如果没变,任务会被标记为 UP-TO-DATE,直接跳过。但有些自定义任务没做好声明,导致每次都重新执行。

task myTask {
    inputs.file('input.txt')   // 声明输入
    outputs.file('output.txt') // 声明输出
    doLast {
        // 只有输入变化时才执行
    }
}

2. 禁用不需要的任务

比如测试任务,如果只是打包,没必要跑测试:

gradle build -x test

或者在构建脚本里按条件禁用:

tasks.named('test') {
    enabled = project.hasProperty('runTests')
}

3. 避免重复配置

我见过有人每个子模块都写一遍相同的依赖配置。其实用 subprojects 统一配置就好:

subprojects {
    apply plugin: 'java'
    repositories {
        mavenCentral()
    }
    dependencies {
        testImplementation 'junit:junit:4.13.2'
    }
}

避坑指南:我曾经在一个大项目里,每个模块都单独声明了 logback 依赖,版本还不一致。结果构建时反复下载不同版本的 jar 包,浪费了大量时间。统一管理依赖版本,用 BOM 或者 version catalog 都能解决。

四、使用分析报告:找到真正的瓶颈

优化之前,先要知道慢在哪里。Gradle 提供了 构建扫描 功能,能生成详细的分析报告。

启用方式很简单:

gradle build --scan

运行后会在终端输出一个链接,打开就能看到:

  • 每个任务的耗时
  • 配置阶段花了多久
  • 哪些任务没有增量执行
  • 依赖下载的耗时

我个人习惯每周跑一次构建扫描,看看有没有异常。有一次我发现某个任务的耗时突然从 2 秒变成了 20 秒,查了半天发现是有人在任务里加了 Thread.sleep(18000)——嗯,调试代码忘了删。

另一个好用的工具是 --profile

gradle build --profile

它会在 build/reports/profile 目录下生成 HTML 报告,展示每个阶段的耗时分布。

建议:把构建扫描集成到 CI 里,每次构建都自动生成报告。这样团队里每个人都能看到构建的健康状况。

知识体系总览

下面这张图总结了本章的核心逻辑,你可以对照着检查自己的项目:

Gradle 构建性能优化核心框架 并行执行 配置优化 避免不必要任务 分析报告 parallel=true workers.max=N 延迟执行(doLast) Provider延迟读取 声明 inputs/outputs -x test 跳过任务 --scan 构建扫描 --profile 耗时报告 优化原则 1. 先测量,再优化 —— 用报告找到真正的瓶颈 2. 少做就是快 —— 避免不必要的任务和重复配置 3. 让 CPU 忙起来 —— 合理利用并行和缓存

实战建议

说了这么多,我建议你从最简单的开始:

  1. 先加 org.gradle.parallel=true,看看构建时间有没有明显下降
  2. 跑一次 --scan,看看哪个任务最慢
  3. 针对最慢的任务,检查是不是配置阶段做了太多事
  4. 把不必要的测试、文档生成等任务跳过

优化是个持续的过程。别指望一次改完所有问题,每次改一点,慢慢积累,构建速度就会越来越快。

最后说一句:构建优化不是炫技,而是为了节省团队的时间。你省下的每一分钟,都是团队多出来的一分钟生产力。


公众号:蓝海资料掘金营,微信deep3321