[Gradle] Implement very simple performance tracking for IdeDependencyResovlers

^KT-55289 Verification Pending
This commit is contained in:
Sebastian Sellmair
2022-12-07 16:29:47 +01:00
committed by Space Team
parent 7a89f4087a
commit d6f855b225
3 changed files with 60 additions and 10 deletions
@@ -17,10 +17,12 @@ import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.re
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.*
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.Companion.logger
import org.jetbrains.kotlin.tooling.core.Extras
import org.jetbrains.kotlin.utils.addToStdlib.measureTimeMillisWithResult
internal class IdeMultiplatformImportImpl(
private val extension: KotlinProjectExtension
private val extension: KotlinProjectExtension,
val statistics: IdeMultiplatformImportStatistics = IdeMultiplatformImportStatistics()
) : IdeMultiplatformImport {
override fun resolveDependencies(sourceSetName: String): Set<IdeaKotlinDependency> {
@@ -59,7 +61,7 @@ internal class IdeMultiplatformImportImpl(
level: DependencyResolutionLevel
) {
registeredDependencyResolvers.add(
RegisteredDependencyResolver(resolver, constraint, phase, level)
RegisteredDependencyResolver(statistics, resolver, constraint, phase, level)
)
if (resolver is IdeDependencyResolver.WithBuildDependencies) {
@@ -159,28 +161,40 @@ internal class IdeMultiplatformImportImpl(
val constraint: SourceSetConstraint,
)
private class RegisteredDependencyResolver(
private data class RegisteredDependencyResolver(
private val statistics: IdeMultiplatformImportStatistics,
private val resolver: IdeDependencyResolver,
val constraint: SourceSetConstraint,
val phase: DependencyResolutionPhase,
val level: DependencyResolutionLevel,
) : IdeDependencyResolver {
private class TimeMeasuredResult(val timeInMillis: Long, val dependencies: Set<IdeaKotlinDependency>)
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
return runCatching { resolver.resolve(sourceSet) }
return runCatching { resolveTimed(sourceSet) }
.onFailure { error -> reportError(sourceSet, error) }
.onSuccess { dependencies -> reportSuccess(sourceSet, dependencies) }
.onSuccess { dependencies -> attachResolvedByExtra(dependencies) }
.getOrNull().orEmpty()
.onSuccess { result -> reportSuccess(sourceSet, result) }
.onSuccess { result -> attachResolvedByExtra(result.dependencies) }
.getOrNull()?.dependencies.orEmpty()
}
private fun resolveTimed(sourceSet: KotlinSourceSet): TimeMeasuredResult {
val (time, result) = measureTimeMillisWithResult { resolver.resolve(sourceSet) }
statistics.addExecutionTime(resolver::class.java, time)
return TimeMeasuredResult(time, result)
}
private fun reportError(sourceSet: KotlinSourceSet, error: Throwable) {
logger.error("e: ${resolver::class.java.name} failed on ${IdeaKotlinSourceCoordinates(sourceSet)}", error)
}
private fun reportSuccess(sourceSet: KotlinSourceSet, dependencies: Set<IdeaKotlinDependency>) {
private fun reportSuccess(sourceSet: KotlinSourceSet, result: TimeMeasuredResult) {
if (!logger.isDebugEnabled) return
logger.debug("${resolver::class.java.name} resolved on ${IdeaKotlinSourceCoordinates(sourceSet)}: $dependencies")
logger.debug(
"${resolver::class.java.name} resolved on ${IdeaKotlinSourceCoordinates(sourceSet)}: " +
"${result.dependencies} (${result.timeInMillis} ms)"
)
}
private fun attachResolvedByExtra(dependencies: Iterable<IdeaKotlinDependency>) {
@@ -189,5 +203,4 @@ internal class IdeMultiplatformImportImpl(
}
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin.ide
/**
* Simple implementation to track dependency resolution bottlenecks.
* This will later be replaced by properly tracing ide import.
*/
internal class IdeMultiplatformImportStatistics {
private val times = mutableMapOf<Class<*>, Long>()
fun addExecutionTime(clazz: Class<*>, timeInMillis: Long) {
times[clazz] = times.getOrDefault(clazz, 0) + timeInMillis
}
fun getExecutionTimes(): Map<Class<*>, Long> {
return times.toMap()
}
fun clear() {
times.clear()
}
}
@@ -13,6 +13,7 @@ import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependencyCoordinates
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.utils.appendLine
import org.jetbrains.kotlin.gradle.utils.notCompatibleWithConfigurationCacheCompat
import org.jetbrains.kotlin.tooling.core.Extras
import java.io.File
@@ -57,6 +58,15 @@ internal open class IdeResolveDependenciesTask : DefaultTask() {
protoOutput.writeBytes(proto)
}
}
(project.kotlinIdeMultiplatformImport as? IdeMultiplatformImportImpl)?.statistics?.let { statistics ->
val timeStatisticsFile = outputDirectory.resolve("times.txt")
timeStatisticsFile.writeText(buildString {
statistics.getExecutionTimes().forEach { (clazz, time) ->
appendLine("${clazz.name} $time.ms")
}
})
}
}
private object IdeDependencyResolverAdapter : JsonSerializer<IdeDependencyResolver> {