Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.

Extremely fast builds with Gradle by Cedric Champeau

RebelLabs is the media partner for the Virtual JUG, the online Java User Group which brings you the best sessions by world class speakers. The best part? You don’t have to leave your house or office to enjoy them! You can educate yourself and become a better developer even from the comfort of your home!

The last vJUG session of 2016 saw Cédric Champeau teach us how we can use Gradle as an extremely fast build tool for our projects. This post will summarise some of the tips Cédric talks about but if you want to learn about Gradle performance in more depth, watch the full video from the master himself! The video is embedded below. Before that though, here’s a little more about Cédric.

Cédric Champeau is a core Groovy committer. He joined SpringSource, a division of VMware, in order to help developing the language. Prior to that, he spent several years at Lingway, a software editor, where he used Groovy in multiple industrial contexts including DSLs for natural language processing, scripting or even workflows. He his currently working on the implementation of static type checking and static compilation for Groovy 2.0.

Extremely fast builds with Gradle

We started with a demo of Gradle. Cédric built a simple “Hello World” Java application from scratch that compiled, built and executed a one class java project. He adding a couple of Gradle plugins and pointed the build script to the main class of the application passing in an argument. For those not used to Gradle, one of the major differences between Maven and Gradle would be instantly clear. The flow of Gradle is created by constructing Gradle scripts, using the Groovy DSL rather than the more familiar XML based constructs you may be used to. We’ll now cover some of the features in Gradle designed to improve build performance.

The Gradle Daemon

The Gradle Daemon sits in the background waiting for build requests to occur. It is a long running process that waits in memory listening for builds to be kicked off. As a benefit of it already running and existing in memory, there are steps that do not need to be run every time a build in invoked making it execute faster overall.

Profiling a build and Scans

You can understand where your build is taking its time, by using build profiling. To enable this feature, add the --profile flag to the gradle command. You’ll get a generated report with information on how long it took to execute your tasks such as build, configuration, and so on. There are also cloud services available that offer build scans that can give you insights into the breakdown of your build. This isn’t restricted to the builds which you yourself run, as the results are published to the cloud. For example for some sample scans take a look here or here.

You can easily view and compare task durations to understand where you’re spending the majority of your time as shown in the snippet below:

Gradle Build Scan

In the Settings and Suggestions tab, you’re given tips on how you can improve your build performance. For instance, the sample below informs you that you’re not using parallel execution and provides you with a link on what it means and how to enable it.

Gradle build tips

This free feature also allows you to share the results of your build, so you can pass the link around among your colleagues to troubleshoot problems.

To apply the build scan feature, you simply need to apply the com.gradle.build.scan feature and agree to the license. To add it to your build on the command line, add -Dscan and you’ll see a url linking to your scan the next time you build.

Incremental Builds

Everyone hates to clean, whether it’s your home or your build environment, nobody wants to do it. The premise of building incrementally is that we shouldn’t need to execute a clean. Our build tool should be able to understand what has been left over from the previous build and know which actions, such as a recompile, are necessary. Gradle has been designed around this premise.

Continuous Builds

If you perform a specific activity again and again, such as make a change to a java file, you might just want to run the compile task rather than the entire build. Well, by enabling continuous builds, using the -t flag, puts gradle into a listener mode that monitors for changes and runs specific tasks based on those changes, such as a Java compilation. Be careful IntelliJ users, your IDE might get more attention from Gradle than you want if you’re saving files on every keystroke!

Composite Builds

Another recent addition to Gradle is the Composite build feature. This allows you to group multiple gradle builds as if they were one. Without this, we’d find ourselves in a dependency mess that requires us to make changes in project a that we need to build, publish and snapshot before our project b can actually make use of the new dependency created by a. Instead, we actually want to replace that binary dependency with something we create from source. Gradle allows to you do just that by copying the source repository of project a into the modules directory of project b. Gradle recognises that you have the source of dependency a that your project b needs locally, so builds and uses this rather than the binary version of a. The module directory was used because that directory was set up in the settings.gradle file in the following loop.

file('modules').listfiles.each { File moduleBuild ->
    includeBuild moduleBuild

Cédric talks about a lot more in the full session, so if you found this post interesting, I’d encourage you watch the session. It’s embedded in this post, so scroll up and check it out!


Read next: