Speed up your Build with Gradle Remote Build Cache

In April 2017 Gradle announced the beta version of their build cache implementation. It is complementary to its incremental build features. As of version 4.0
the build cache became production-ready.
How does it work? Gradle uses the inputs of a task as a key to uniquely identify the output for a task. Instead of executing the task again, Gradle will copy the outputs from the cache directly into the build directory. This can be much faster than re-executing the whole task. This can be especially beneficial when switching branches frequently and having many modules in your project.
Gradle is using the build cache since November 2016 and saw a median build time reduction of 15% [1]. Since our clean builds are taking almost 3 minutes, I wanted to investigate the remote cache for our setup.
Gradle Build Cache Node
Gradle Enterprise comes by default with a bundled build cache. But Gradle also released a Docker image of a build cache node, which can be found on Docker Hub.
It can be connected to Gradle Enterprise for centralised management, but also be used without it (with restricted functionality). The full documentation can be found here.
When running the Docker image, it is important to mount a persistent storage so that the cache won’t be purged when restarting the image.

Once you deployed the node (e.g. on http://gradle-build-cache.mycompany.com/
), you can configure it via a web interface.
The target cache size is by default set to 1 GB. When it is full, items that have been used least recently will be evicted from the cache once new items are pushed to the cache. It is thus recommended to increase it [2]. We set it to 20 GB. Since our build artifacts should be smaller than 100 MB, we did not adjust the maximum artifact size. You can also specify different cache access control.
Project configuration
The build cache in your project is not enabled by default. You explicitly need to enable it. There are multiple ways:
- For current build: run build with
--build-cache
- For project: add
org.gradle.caching=true
to your$PROJECT_ROOT/gradle.properties
- For all builds for current user: add
org.gradle.caching=true
to your$GRADLE_HOME/gradle.properties
The recommended setup for the build cache is that your continuous integration server populates the remote build cache with the artifacts of clean builds. Developers will just pull from the remote cache and push to a local build cache [3].

This configuration can be achieved by adding
ext.IS_CI_RUN = System.getenv().containsKey("CI_RUN")buildCache {
local {
enabled = !IS_CI_RUN
}
remote(HttpBuildCache) {
url = 'http://«remote-cache-node-hostname»/cache/'
push = IS_CI_RUN
}
}
to settings.gradle
, where «remote-cache-node-hostname»
needs to be replaced with your specific hostname. You can also configure credentials in order to access the remote cache and configure the local cache target size and directory. Please consult the build cache user guide for more information.
Kotlin Projects
Projects using Kotlin should upgrade its version to >=1.2.20
to make use of build caching. Since Gradle does not yet have a way to map inputs and outputs for annotation processors, caching is disabled by default for kapt
. You can explicitly enable it with
kapt {
useBuildCache = true
}
Note: Gradle is working on making incremental compilation and thus build caching in general more efficient in the presence of annotation processors. There is an issue on Github, where you can find the current state of development.
Android Projects
As some Android plugin versions have issues with build caching, Gradle created a plugin that applies workarounds. It can be found here. Gradle version 4.1+
and Android plugin versions 3.x
are supported. With Android plugin versions >=3.1
the plugin is only required if you are using Android’s data binding. The plugin can be simply applied in the root Gradle script:
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "gradle.plugin.org.gradle.android:android-cache-fix-gradle-plugin:0.3.3"
}
}apply plugin: "org.gradle.android.cache-fix"
Results
Our Android project currently consists of one large and five rather small modules. Thus a huge benefit was not expected when adding remote build caching. During the setup the Gradle from version was upgraded from4.1
to 4.5.1
, the Android cache fix plugin and build caching applied as described before.
Clean builds sped up from 2 min 46 sec to 2 min 13 sec which is equivalent to a performance gain of about 20 %. Moving to a more modular project organisation would probably lead to more performance benefits.
Sources
[1] https://blog.gradle.org/introducing-gradle-build-cache
[2] https://docs.gradle.com/enterprise/admin/current
[3] https://docs.gradle.org/current/userguide/build_cache.html
[4] https://www.slideshare.net/emwendelin/whats-new-in-gradle-40