First, in your gradle-wrapper.properties, add this:
org.gradle.caching=true
org.gradle.parallel=true
and see if it helps. It should.
Second, you might want to implement a TaskExecutionListener and register it with gradle.taskGraph.addTaskExecutionListener. The advice comes from Peter Niederwieser himself.
In short, in your top-level gradle.build, copy this:
import java.util.concurrent.TimeUnit
class TimingsListener implements TaskExecutionListener, BuildListener {
private long startTime
private timings = []
@Override
void beforeExecute(Task task) {
startTime = System.nanoTime()
}
@Override
void afterExecute(Task task, TaskState taskState) {
def ms = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
timings.add([ms, task.path])
task.project.logger.warn "${task.path} took ${ms}ms"
}
@Override
void buildFinished(BuildResult result) {
println "Task timings:"
for (timing in timings) {
if (timing[0] >= 50) {
printf "%7sms %s\n", timing
}
}
}
@Override
void buildStarted(Gradle gradle) {}
@Override
void projectsEvaluated(Gradle gradle) {}
@Override
void projectsLoaded(Gradle gradle) {}
@Override
void settingsEvaluated(Settings settings) {}
}
gradle.addListener new TimingsListener()
And the output might look like:
gradlew build
> Task :compileJava UP-TO-DATE
:compileJava took 3255ms
> Task :processResources UP-TO-DATE
:processResources took 10ms
> Task :classes UP-TO-DATE
:classes took 0ms
> Task :bootWar UP-TO-DATE
:bootWar took 637ms
> Task :war SKIPPED
:war took 0ms
> Task :assemble UP-TO-DATE
:assemble took 0ms
> Task :compileTestJava UP-TO-DATE
:compileTestJava took 427ms
> Task :processTestResources UP-TO-DATE
:processTestResources took 5ms
> Task :testClasses UP-TO-DATE
:testClasses took 0ms
> Task :test UP-TO-DATE
:test took 62ms
> Task :check UP-TO-DATE
:check took 0ms
> Task :build UP-TO-DATE
:build took 0ms
Task timings:
3255ms :compileJava
637ms :bootWar
427ms :compileTestJava
62ms :test
BONUS
You can also speed up your tests by having this in your build.gradle:
test {
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
}
Note that if you do run the tests in parallel, you will have to ensure that they are independent, i.e. don’t share resources, be that files, databases or something else. Otherwise there is a chance that the tests will interfere with each other in random and unpredictable ways.