并行构建耗时不降反升,首要排查是否真正生效:检查隐式模块依赖、验证--dry-run输出是否交错,并确认org.gradle.daemon=true、org.gradle.caching=true、org.gradle.configuration-cache=true均已启用;再通过--profile定位kapt、AAPT2等串行瓶颈任务。

并行构建开启后耗时不降反升,先看是否真在并行
很多情况下你以为开启了 --parallel 或 org.gradle.parallel=true,其实根本没生效。Gradle 会自动跳过并行——只要模块间存在未声明的隐式依赖(比如 A 模块通过反射调用 B 模块的类,但没在 build.gradle 里声明 implementation project(':B')),它就会退回到串行模式,且不报错、不警告。
验证方式很简单:执行 ./gradlew build --dry-run --console=plain,观察输出里任务是否按模块分组交错出现。如果所有 :moduleA:compileJava、:moduleB:compileJava 等任务是严格上下排列(非交错),说明并行被静默禁用了。
- 检查所有
subprojects或allprojects块里有没有全局apply plugin或动态repositories配置——这些会让 Gradle 强制串行化配置阶段 - 运行
./gradlew dependencies --configuration compileClasspath,确认跨模块引用是否都显式声明;漏掉的api/implementation依赖是常见诱因 - 在
settings.gradle中启用enableFeaturePreview('typesafe-project-accessors')(Gradle 8.4+)可让 IDE 和构建更早暴露模块引用缺失问题
线程争抢资源比串行还费劲,得看 org.gradle.workers.max
默认情况下 org.gradle.parallel=true 会使用全部可用 CPU 核心数,但实际构建中真正吃 CPU 的环节(如 Java 编译、Kotlin 编译、AAPT2)往往受限于内存或磁盘 I/O。线程开太多反而触发频繁 GC 或磁盘排队,尤其在 SSD 性能一般或内存不足(-Xmx 小于 3g)的机器上。
- 先查真实 CPU 核心数:
nproc(Linux/macOS)或Get-CimInstance Win32_Processor | Select-Object NumberOfLogicalProcessors(PowerShell) - 把
org.gradle.workers.max设为 CPU 逻辑核数的 0.75 倍(例如 16 核设为 12),再测一次time ./gradlew clean assembleDebug -x test - 同时打开
jconsole连接正在运行的 Gradle daemon,观察 “Threads” 标签页里活跃线程是否长期卡在WAITING或BLOCKED状态——这是资源争抢的直接证据
并行只是放大器,不是万能解药
并行构建只加速“可并行的任务”,而 Android/Java 项目里真正拖慢构建的,常是那些无法并行的瓶颈环节:kapt 注解处理、资源合并(mergeDebugResources)、AAPT2 链接、Dexer 合并等。这些任务天然串行,且单个耗时远超编译本身。开启并行后,它们反而成了木桶最短那块板,总耗时可能不减反增。
- 运行
./gradlew assembleDebug --profile,打开生成的build/reports/profile/...HTML 报告,重点看 “Task Execution” 表格顶部几项耗时是否集中(比如kaptGenerateStubsDebugKotlin占 42 秒,其余任务加起来才 18 秒) - 如果是 kapt 重灾区,优先迁移到
KSP(Kotlin Symbol Processing)——Room/Dagger/Hilt 项目实测可砍掉 60%+ 的注解处理时间 - 对资源类任务,检查是否启用了
android.useNewResourceProcessing=true(AGP 8.0+ 默认开启),以及是否误启了android.enableAapt2=false(已废弃,强制关闭会导致回退到极慢的 aapt)
守护进程和配置缓存没配好,并行就是空中楼阁
并行构建的前提是每次构建都能复用前一次的 daemon 进程和配置结果。如果 org.gradle.daemon=false 或 org.gradle.configuration-cache=true 没启用,每次构建都要重新解析全部 build.gradle、加载插件、构建 DAG 图——这部分耗时本身就可能超过并行带来的收益,尤其在模块数 > 30 的项目中。
- 确认
gradle.properties里这四行都存在且未被注释:org.gradle.daemon=true、org.gradle.parallel=true、org.gradle.caching=true、org.gradle.configuration-cache=true - 首次启用配置缓存时,务必加
--configuration-cache参数运行一次完整构建(如./gradlew build --configuration-cache),否则缓存不会生成 - 若项目含自定义 Gradle 插件,需检查其是否兼容配置缓存——在
gradle.properties加org.gradle.configuration-cache-problems=warn,构建时会明确提示哪一行代码破坏了缓存
真正卡住的地方,往往不是并行开关本身,而是模块边界模糊、I/O 被打满、或者某个串行任务悄悄吞掉了 80% 的时间。别急着调 workers.max,先跑一次 --profile,盯着报告里耗时最长的前三项——它们才是该动刀子的地方。


















