Track execution time per task in gradle script?

后端 未结 8 2124
深忆病人
深忆病人 2021-01-30 06:37

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

相关标签:
8条回答
  • 2021-01-30 07:03

    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'
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-30 07:09

    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.
    
    0 讨论(0)
  • 2021-01-30 07:15

    The cleanest solution is to implement a TaskExecutionListener (I'm sure you can handle that part) and register it with gradle.taskGraph.addTaskExecutionListener.

    0 讨论(0)
  • 2021-01-30 07:18

    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()
    
    0 讨论(0)
  • 2021-01-30 07:21

    In Android Studio version >= 4.0 added build analyzer, which track execution time per task in gradle.

    Find here after success build:

    0 讨论(0)
  • 2021-01-30 07:22

    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()
    
    0 讨论(0)
提交回复
热议问题