Faster Gradle Task Execution : A small step

Nishi Doshi
4 min readDec 13, 2020

While working on Android Studio what fascinated me was sometimes build time for the project was quite small than other times. I dived deep into understanding what was happening and here I am sharing a small piece of knowledge to fasten gradle tasks.

Let’s first look into one statement what caught a lot of attention during this exploration :

8 actionable tasks: 1 executed, 7 up-to-date

When we run any gradle task(for example : gradle assembleDevDebug), it executes certain internal tasks in Android. [This is a sample task from one of my Android projects and hence what internal tasks were run will be covered in future posts :) ]

Breaking down the output that we receive on the screen into three parts :

  1. Actionable tasks : Totals tasks that were asked to run by the user
  2. Executed : Tasks that were executed
  3. Up-to-date : Tasks that did not need to run

Before diving into what are the reasons for certain tasks executing and not executing, let’s take a very simple example described below :

def exampleNumber = 2
def sampleOutputFolder = file("$buildDir")
task sample() { inputs.property "examplenumber", exampleNumber
outputs.file(sampleOutputFolder)

doLast {
for (int i = 0; i < exampleNumber; i++) {
println("Sample print")
}
}
}

Above task is responsible for printing "Sample print" on a new line exampleNumer of times. There is also an outputFile declared which is not used anywhere currently (but this is kept intentionally which will become handy in the last section of the article).

Let’s run the task with gradle sample --info command multiple times with some changes and analyze the output we receive on every run and change.

  1. On the first run, we observe :
Task 'sample' is not up-to-date because:
No history is available.

This was the first time task was executed as it was not up-to-date as no history of it was available [An expected behavior].

2. Running the same task second time and/or multiple times, we observe :

Skipping task sample as it is up-to-date.

We observe that as the task is up-to-date, task execution is skipped.

3. Now let’s change exampleNumber to a different value (let’s say 5). Post changing when we run the task and we observe :

Task sample is not up-to-date because:
One or more additional actions for task sample have changed.

We observe that when we changed a value that was defined as an input property to the task it was stated not to be up-to-date and hence ran the task again.

As clear from the analysis done above, the reason why certain times task was executed and certain times skipped is :

Gradle has an inbuilt support for executing the tasks for which either of inputs or outputs from the last execution have changed.

As we changed the value registered as an input exampleNumber in our 3rd run, we observe that it was ran again. Similar observation can be found when we delete the outputDirectory and keep our input constant that was registered.

A very similar exploration that I made as an Android Developer : when you Clean Build your in your project, it essentially deletes the outputs of tasks executed while building the project and runs all those tasks again. While running again, although inputs were constants output directories have been changed. Hence, Clean Build takes more time to run gradle tasks compared to Build.

But wait, the explorations aren’t yet over. Many people on learning this might think that the key to fasten their builds is a constant value of input or outputs. You might think of breaking down your tasks with smaller input values to lessen the time spent on tasks. However, here is a side effect I found :

In case you do not have an output registered, your gradle task will run every single time. Why? Let’s check out by removing outputDir registered as output in above example. On several runs, you will observe task is being executed always with the reason :

Task sample is not up-to-date because:
Task has not declared any outputs despite executing actions.
And here are some references that helped me grow my knowledge :

And here, we remember the bold parts of the reason stated in italics above.

Either of inputs or outputs”

In case of either of them not being registered for monitoring, gradle will keep running the tasks. Thus, the key to fasten your gradle tasks is not only keeping input and output constant but also registering them as well.

I hope this lesson will help you fasten your gradle tasks. Also, there are many more such small exploration posts that I will be sharing in the near future.

Stay Tuned!

Happy Reading!

--

--

Nishi Doshi

Software Engineer at Microsoft | Android Platform Enthusiast | Machine Learning Enthusiast | Technology is love