Gradle 9.7 Parallel Configuration Nearly Doubles Android Sync Speed
Android recently collaborated with the Gradle team to introduce the new Gradle Isolated Projects in version 9.7.0. Simply put, Gradle is now changing the 'configuration phase' of large multi-module projects into an architecture that can safely run in parallel, while also enabling per-module incremental caching in the future.
For Android development, Gradle Projects like app, feature-home, core-network, and core-ui previously appeared to be independent modules, but during the configuration phase, they could actually read and write each other's state. This made it difficult for Gradle to safely configure them concurrently. Now, Isolated Projects imposes a strong constraint boundary between these Projects, allowing parallel configuration. Starting with Gradle 9.7, this support has been promoted from experimental to incubating, and it will become the default mode in the future.
A future Gradle build will generally look like this:
Initialization
↓
Configuration
↓
Execution
Read settings Execute each module's build.gradle javac/kotlinc/package...
Create Tasks
Configure Plugins
Resolve various Project states
A large portion of the time spent on what everyone calls Android Studio's Sync Project with Gradle Files is consumed by the Configuration phase. For example, in a large project with 500 modules, the logic was previously close to:
:app
│
├─ configure
↓
:core
│
├─ configure
↓
:network
│
├─ configure
↓
:feature-home
│
├─ configure
↓
...
However, in the past, this configuration behavior could not simply be thrown into a thread pool because Gradle's historical Build DSL allowed patterns like this:
// :app/build.gradle.kts
val version = rootProject.version
project(":network").tasks.named("xxx") {
...
}
rootProject.subprojects {
// Modify other projects
}
This means that while A is being configured, it can touch B, and B might touch C:
Project A configuration
│
├──────────► Project B mutable state
│
└──────────► Root Project mutable state
If you try to run them synchronously in a multi-threaded environment, Gradle cannot guarantee execution order and state consistency. Callback order and plugin behavior would become chaotic, and task registration could also have problems. Therefore, Gradle multi-module projects have long suffered from a serious 'shared mutable state during configuration' problem. The core thing Isolated Projects does is actually quite simple; it mainly stipulates:
:app
┌─────────┐
│ mutable │
│ state │
└─────────┘
X
│ Forbidden to touch directly
X
┌─────────┐
│ mutable │
│ state │
└─────────┘
:network
Each Project's configuration logic can only safely operate on its own mutable state. For example:
rootProject.version
project(":foo").tasks
project(":foo").dependencies
project(":foo").configurations
project(":foo").extensions
This kind of cross-Project 'reading/modifying mutable state' will be judged by Gradle as an Isolated Projects violation. The official recommendation can be simply understood as:
Except for a few immutable getters, basically do not call anything on another
Project.
Immutable information determined before configuration starts, such as another Project's name, path, projectDir, and buildFile, can still be read. So in reality, this establishes a new concurrency contract on the Gradle DSL. With this contract, you can achieve:
Before
Project A ──► B
│ ▲
▼ │
Project C ◄──┘
Don't know who depends on whose state
→ Cannot parallelize
Isolated Projects
┌ A ┐ ┌ B ┐ ┌ C ┐ ┌ D ┐
└───┘ └───┘ └───┘ └───┘
│ │ │ │
CPU1 CPU2 CPU3 CPU4
→ Can safely configure in parallel
So the major practical benefit of Gradle 9.7 is Parallel Project Configuration.
During an Android Studio Sync, the Studio asks Gradle to build a large number of Tooling Models, for example:
Gradle
:app
├─ Android model
├─ dependency model
├─ source sets
└─ variants
:featureA
├─ Android model
├─ dependency model
└─ variants
:featureB
...
│
▼
Android Studio
Previously, because Project configuration itself had shared state, the parallelism for the IDE to fetch these models was always limited. But now, with Isolated Projects enabled:
CPU 1 → configure :app → model
CPU 2 → configure :featureA → model
CPU 3 → configure :featureB → model
CPU 4 → configure :core → model
CPU 5 → configure :network → model
The results from Gradle's own official test project are quite significant:
For a 5000+ Project Android monorepo, it can even achieve an optimization from 5m09s -> 2m44s. So while the perception for a typical app with a dozen modules might be average, the impact on an Android monorepo with hundreds to thousands of modules is quite significant.
Furthermore, it is actually on the same track as Configuration Cache, which can be roughly understood as:
Configuration Cache
│
│ Solves:
▼
Last configuration unchanged?
→ Then skip the entire Configuration run this time
Isolated Projects
│
│ Solves:
▼
Configuration must re-run?
→ Then run each Project in parallel
So the overall architecture situation is roughly like:
Configuration Cache
│
┌────────┴────────┐
│ │
Cache Hit Cache Miss
│ │
Configuration Isolated
Fully Skipped Projects
│
Project A ─┬─ Project B
├─ Project C
└─ Project D
Parallel Configuration
That is, Isolated Projects is actually built directly on top of the Configuration Cache infrastructure. Therefore, enabling org.gradle.isolated-projects=true will cause Gradle to automatically enable Configuration Cache. Explicitly turning off Configuration Cache will even result in an error.
However, it is completely different from org.gradle.parallel=true. parallel mainly solves:
Execution Phase
:app:compile
:libA:compile
:libB:compile
↓
Task Parallelism
While Isolated Projects solves:
Configuration Phase
configure :app
configure :libA
configure :libB
↓
Project Configuration Parallelism
These two are not the same thing. However, Gradle officially stated that this support was implemented in collaboration with Google and JetBrains, meaning the project, the IDE, all participated in this optimization.
But older projects might face some risks. For example, if custom Gradle scripts or third-party plugins have cross-project access, enabling Gradle Isolated might directly cause configuration failures.
But honestly, for the China region, the biggest time sink for Sync is not here at all. In reality, this optimization is mostly negligible, and upgrading to Gradle 9.7.0 still requires a lot of courage.
Top 1 from juejin.cn, machine-translated. The original thread is authoritative.
These Android folks have nothing else to do all day but tinker with Gradle.