Hi team! I was looking into a way to track local b...
# performance
m
Hi team! I was looking into a way to track local build times. I've noticed that BuildListener#buildFinished is now deprecated given that configuration-cache is enabled. What would be the best way to tackle this? Do you happen to know any other APIs for it? I feel like this approach might be a little bit too naive - and also it does not include configuration phase đŸ€”
Copy code
tasks.configureEach { task ->
    if (task.name.startsWith("assembleDebug")) {
        println "Track start time"
        task.doLast {
            println "Track end time"
        }
    }
}
Running benchmarks is of course an option but I wanted to see an overall trend on a day-to-day develoment among devs.
I assume we could just run every build with
--profile
option and parse the results - but wouldn't that slow down the overall build?
a
Gradle company provides a paid product called Develocity that does exactly what you are looking for and more, and of course integrated with Gradle in the best way possible. You can see the local build time and all other details in a build scan, which you can try out even without buying Develocity just by running any build with
--scan
. If you still prefer a home-cooked solution, the javadoc to the method you linked points you to the
FlowProviders.getBuildWorkResult()
in the “see also” section. This is a Configuration Cache compatible replacement for the deprecated method. Here are more docs on this: https://docs.gradle.org/current/userguide/dataflow_actions.html
m
Thank you @Alex Semin - I'm still in the process of convincing my employer to sign up for Develocity as I think it's a great tool! I've seen BuildWorkResult but got blindsided by it only containing
failure
field. Now I realise that I can just observe it and hook up start time / end time within. Thanks!
👍 1
Hey @Alex Semin correct me if I'm wrong but it seems that FlowProviders api will only let me know when build completes and not when the build starts, right? The
startTime
value here would be cached as soon as the plugin is applied đŸ€”
Copy code
@Suppress("UnstableApiUsage")
abstract class BuildTimeTracker : Plugin<Project> {

  @get:Inject
  abstract val flowScope: FlowScope

  @get:Inject
  abstract val flowProviders: FlowProviders
  
  override fun apply(target: Project) {
    flowScope.always(BuildTimeTrackAction::class.java) {
      val startTime = System.currentTimeMillis()
      it.parameters.buildTime.set(
        flowProviders.buildWorkResult.map {
          System.currentTimeMillis() - startTime
        },
      )
    }
  }
}

@Suppress("UnstableApiUsage")
abstract class BuildTimeTrackAction : FlowAction<Params> {

  interface Params : FlowParameters {
    @get:Input
    val buildTime: Property<Long>
  }

  override fun execute(parameters: Params) {
    println("Build time: ${parameters.buildTime.get()}ms")
  }
}
a
FlowProviders api will only let me know when build completes
That’s correct. Currently, it’s the only use-case for the API
The
startTime
value here would be cached as soon as the plugin is applied đŸ€”
Correct, the plugin application (and the whole configuration phase) can be skipped on a Configuration Cache hit, for instance. I am unsure if there is a public API for the start time of the build. However, there are many existing open-source plugins that try to measure the same thing. Maybe they can give inspiration 🙃