JDK 17: Using ParallelGC for the Kotlin process in Android Builds
Tags: gradle, android, kotlin
Published: 2023-05-10 20:56:48

In the previous [article](https://dev.to/cdsap/using-parellgc-for-the-kotlin-process-in-android-builds-2geh), we explained the results of using ParallelGC in the Kotlin process for the project [nowinandroid](https://github.com/android/nowinandroid). The results showed:
* 22% Kotlin Compile aggregated task time improvement
* 60% garbage collector time improvement of the Kotlin process
* 51% usage reduction of the Kotlin process memory usage

The article measured the project using AGP 7.4.1 and JDK 11. Since AGP 8.0.0, the min version required is JDK 17 and we have pending to repeat the experiment on different types of GCs in the current tooling. This article shows the results found when using AGP 8.0.0 and JDK 17 with the different types of garbage collectors.

## Experiment

### Environment
* Linux 5.15.0-1035-azure (amd64)
* 2 CPU cores
* 2 Gradle workers
* 3 Gb memory heap size
* Github Action agent

### Project
* [nowinandroid](https://github.com/android/nowinandroid) (commit [c746b6afcdeef23ae00ae4ec0d1d403ef28e62e2](https://github.com/android/nowinandroid/commit/c746b6afcdeef23ae00ae4ec0d1d403ef28e62e2) - 04/27)
* JDK 17
* Gradle 8.1
* AGP 8.0.0
* KGP 1.8.10
* Hilt 2.44.2



## Experiment Variants

| id         | Gradle GC     | Kotlin GC       |
|------------|-------------|--------------|
| gg_kg      | G1          |     G1       |
| gp_kg      | ParallelGC  |     G1       |
| gg_kp      | G1          | ParallelGC   |
| gp_kp      | ParallelGC  | ParallelGC   |
 

## Methodology
* Each variant runs 40 Gradle profiler scenarios
* Each scenario runs one warm-up and five builds
* Each scenario applies a Gradle profiler scenario with an abi change on the module core:datastore(Highest betweenness centrality in the project dependency graph).
The task executed for each scenario is clean :app:assembleDebug
* This type of scenario generates for each execution:
  * 540 tasks executed
  * 26 Kotlin Compiler tasks executed in 12 projects
  * 28 Java Compiler tasks executed in 12 projects
  * We have ignored the warm-up and first build in all the results of each execution

## Results

### Builds
Data extracted from the outputs generated for each Gradle Profiler execution, duration in milliseconds

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf2ad8v7x6jmf8ttnjko.png)

Mean by variant
 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpkf488krzyqjpy84wo9.png)

### Kotlin Compiler
Aggregated build time of the Kotlin Compiler tasks with the outcome "SUCCESS" using Gradle Enterprise API, duration in milliseconds:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7xboije38mjnb2kb451o.png)

Mean by variant
 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zwjg3twpq86dkgabx3nk.png)


### Kotlin process
Retrieving the Kotlin process information using [InfoKotlinProcess](https://github.com/cdsap/InfoKotlinProcess):
**GC Time**
Garbage Collector time in minutes:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxhikj7e8ew48lr4s7xt.png)
 
Mean by variant
 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1gm7up7rtrzc1y1qcrqg.png)


**Usage**
Kotlin process usage in GB:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j4c5f0wqvzlebrdsuavb.png)

Mean by variant

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy0xg9b6t497k8ngpt6b.png)

### ZGC
The Z Garbage Collector, also known as ZGC, is a scalable low latency garbage collector. ZGC was initially introduced as an experimental feature in JDK 11, and was declared Production Ready in JDK 15. Because Android projects target JDK 17, we could use this type of collector in our experiments. 

Our first attempt to add two additional variants failed, the variant using ZGC for the Gradle and Kotlin processes showed a significant memory pressure on the Gradle Daemon, this situation affects the measurements on the Kotlin process, Gradle process performance:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7j2hv4x62m3oe6x2h99.png) 

Kotlin process:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5obwaomj39doqa58hv2n.png)

With that, I don't want to say that ZGC is not suitable for Android builds. In this case, I think the short memory configuration for the Android environment in Github Action(3Gb for the Gradle process) is causing the slower build times for both processes. 

However, we could ignore the variant gz_kz and focus on the results of using ZGC for the Kotlin process and Parallel for Gradle process(gp_kz). 

## Experiment Variants

| id         | Gradle GC     | Kotlin GC       |
|------------|-------------|--------------|
| gg_kp      | G1          | ParallelGC   |
| gp_kp      | ParallelGC  | ParallelGC   |
| gp_kz      | ParallelGC  | ZGC   |

#### Results
These results have ignored the slowest variants in the experiments for the Kotlin process (gp_kg and gg_kg).

**Build time**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5gr2wuai8u9yilznqit.png)

Mean by variant

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqq5b3up53qgwm823vdm.png)

### Kotlin Compiler

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obwigd0ibgzt0f9044hg.png)

Mean by variant

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3z2rnn0lv2fwb17kk8b.png)

## Final words
The combination of ParallelGC for both processes is again giving the best result for Build times and Kotlin compiler task durations. 
The new ZGC for the Kotlin process is promising, given the constrained environment where the experiments were executed. 
As we mentioned in the previous article, you need to measure what matters in your project, CI pipelines could contain expensive builds with R8 tasks or endless test tasks, and we just covered assembleDebug.

Happy Building