What is the most elegant way to track the execution times on how long a task took in a gradle build script? In an optimal case log the time directly same or next line to the tas
I know this is an old question, but I've found a cool plugin that does task timing. It's like @jlevy's answer, but with some more options available: https://github.com/passy/build-time-tracker-plugin
This plugin by Pascal Hartig continuously logs your build times and provides CSV and bar chart summaries. The developer recommends it for monitoring your build times over time, versus --profile
which gives you a snapshot for the current build.
This is how I'm currently using it:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "net.rdrei.android.buildtimetracker:gradle-plugin:0.7.+"
}
}
apply plugin: "build-time-tracker"
buildtimetracker {
reporters {
summary {
ordered false
threshold 50
barstyle 'unicode'
}
}
}
I have tried with @Jilevys solution but was getting error in finding the class org.gradle.util.Clock()
I have modified it to use Java8 classes. Put below code on top of the build.gradle
import java.time.LocalDateTime
class TimingsListener implements TaskExecutionListener, BuildListener {
private LocalDateTime taskStartTime
@Override
void beforeExecute(Task task) {
taskStartTime = LocalDateTime.now();
}
@Override
void afterExecute(Task task, TaskState taskState) {
LocalDateTime taskEndTime = LocalDateTime.now();
def seconds = Duration.between(taskStartTime, taskEndTime).toSeconds();
task.project.logger.warn "${task.path} took ${seconds} seconds."
}
@Override
void buildStarted(Gradle gradle) {
project.logger.warn "Build started on "+LocalDateTime.now()
}
@Override
void settingsEvaluated(Settings settings) {
}
@Override
void projectsLoaded(Gradle gradle) {
}
@Override
void projectsEvaluated(Gradle gradle) {
}
@Override
void buildFinished(BuildResult result) {
project.logger.warn "Build finished on "+LocalDateTime.now()
}
}
gradle.addListener new TimingsListener()
It produces output similar to given below.
<projectname>:<taskName> took 10 seconds.
The cleanest solution is to implement a TaskExecutionListener (I'm sure you can handle that part) and register it with gradle.taskGraph.addTaskExecutionListener
.
This is a variation of jlevy's answer which has been modified to remove the usage of the publicly accessible gradle Clock
class, which has been deprecated.
BUILD SUCCESSFUL
Total time: 1 mins 37.973 secs
Task timings:
579ms :myproject-foo:clean
15184ms :myproject-bar:clean
2839ms :myproject-bar:compileJava
10157ms :myproject-bar:jar
456ms :myproject-foo:compileJava
391ms :myproject-foo:libs
101ms :myproject-foo:jar
316ms :myproject-bar:compileTestJava
364ms :myproject-foo:compileTestJava
53353ms :myproject-foo:test
2146ms :myproject-bar:test
8348ms :www/node:npmInstall
687ms :www/node:npmTest
Something like the code below can be dropped into your top level build.gradle
to report timings during execution, or after completion.
import java.util.concurrent.TimeUnit
// Log timings per task.
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()
In Android Studio version >= 4.0 added build analyzer, which track execution time per task in gradle.
Find here after success build:
Just to elaborate on Peter Niederwieser's answer: We wanted to do the same thing, as well as a report timings at the end of the build, so slow steps are obvious (and appropriate parties feel a small but healthy bit of shame when they slow down the build!).
BUILD SUCCESSFUL
Total time: 1 mins 37.973 secs
Task timings:
579ms :myproject-foo:clean
15184ms :myproject-bar:clean
2839ms :myproject-bar:compileJava
10157ms :myproject-bar:jar
456ms :myproject-foo:compileJava
391ms :myproject-foo:libs
101ms :myproject-foo:jar
316ms :myproject-bar:compileTestJava
364ms :myproject-foo:compileTestJava
53353ms :myproject-foo:test
2146ms :myproject-bar:test
8348ms :www/node:npmInstall
687ms :www/node:npmTest
Something like the code below can be dropped into your top level build.gradle
to report timings during execution, or after completion.
// Log timings per task.
class TimingsListener implements TaskExecutionListener, BuildListener {
private Clock clock
private timings = []
@Override
void beforeExecute(Task task) {
clock = new org.gradle.util.Clock()
}
@Override
void afterExecute(Task task, TaskState taskState) {
def ms = clock.timeInMs
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()