Add GC metric to build statistic
This commit is contained in:
committed by
Space Team
parent
c16dabba1f
commit
a34657195b
@@ -10,12 +10,14 @@ import java.io.Serializable
|
||||
data class BuildMetrics(
|
||||
val buildTimes: BuildTimes = BuildTimes(),
|
||||
val buildPerformanceMetrics: BuildPerformanceMetrics = BuildPerformanceMetrics(),
|
||||
val buildAttributes: BuildAttributes = BuildAttributes()
|
||||
val buildAttributes: BuildAttributes = BuildAttributes(),
|
||||
val gcMetrics: GcMetrics = GcMetrics()
|
||||
) : Serializable {
|
||||
fun addAll(other: BuildMetrics) {
|
||||
buildTimes.addAll(other.buildTimes)
|
||||
buildPerformanceMetrics.addAll(other.buildPerformanceMetrics)
|
||||
buildAttributes.addAll(other.buildAttributes)
|
||||
gcMetrics.addAll(other.gcMetrics)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.build.report.metrics
|
||||
|
||||
import java.lang.management.ManagementFactory
|
||||
|
||||
interface BuildMetricsReporter {
|
||||
fun startMeasure(time: BuildTime)
|
||||
fun endMeasure(time: BuildTime)
|
||||
@@ -14,6 +16,11 @@ interface BuildMetricsReporter {
|
||||
fun addMetric(metric: BuildPerformanceMetric, value: Long)
|
||||
fun addTimeMetric(metric: BuildPerformanceMetric)
|
||||
|
||||
//Change metric to enum if possible
|
||||
fun addGcMetric(metric: String, value: GcMetric)
|
||||
fun startGcMetric(name: String, value: GcMetric)
|
||||
fun endGcMetric(name: String, value: GcMetric)
|
||||
|
||||
fun addAttribute(attribute: BuildAttribute)
|
||||
|
||||
fun getMetrics(): BuildMetrics
|
||||
@@ -27,4 +34,17 @@ inline fun <T> BuildMetricsReporter.measure(time: BuildTime, fn: () -> T): T {
|
||||
} finally {
|
||||
endMeasure(time)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun BuildMetricsReporter.startMeasureGc() {
|
||||
ManagementFactory.getGarbageCollectorMXBeans().forEach {
|
||||
startGcMetric(it.name, GcMetric(it.collectionTime, it.collectionCount))
|
||||
}
|
||||
}
|
||||
|
||||
fun BuildMetricsReporter.endMeasureGc() {
|
||||
ManagementFactory.getGarbageCollectorMXBeans().forEach {
|
||||
endGcMetric(it.name, GcMetric(it.collectionTime, it.collectionCount))
|
||||
}
|
||||
}
|
||||
+22
-1
@@ -13,9 +13,11 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
||||
EnumMap(
|
||||
BuildTime::class.java
|
||||
)
|
||||
private val myGcPerformance = HashMap<String, GcMetric>()
|
||||
private val myBuildTimes = BuildTimes()
|
||||
private val myBuildMetrics = BuildPerformanceMetrics()
|
||||
private val myBuildAttributes = BuildAttributes()
|
||||
private val myGcMetrics = GcMetrics()
|
||||
|
||||
override fun startMeasure(time: BuildTime) {
|
||||
if (time in myBuildTimeStartNs) {
|
||||
@@ -30,6 +32,19 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
||||
myBuildTimes.addTimeNs(time, durationNs)
|
||||
}
|
||||
|
||||
override fun startGcMetric(name: String, value: GcMetric) {
|
||||
if (name in myGcPerformance) {
|
||||
error("$name was restarted before it finished")
|
||||
}
|
||||
myGcPerformance[name] = value
|
||||
}
|
||||
|
||||
override fun endGcMetric(name: String, value: GcMetric) {
|
||||
val startValue = myGcPerformance.remove(name) ?: error("$name finished before it started")
|
||||
val diff = value - startValue
|
||||
myGcMetrics.add(name, diff)
|
||||
}
|
||||
|
||||
override fun addTimeMetricNs(time: BuildTime, durationNs: Long) {
|
||||
myBuildTimes.addTimeNs(time, durationNs)
|
||||
}
|
||||
@@ -47,6 +62,10 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
||||
|
||||
}
|
||||
|
||||
override fun addGcMetric(metric: String, value: GcMetric) {
|
||||
myGcMetrics.add(metric, value)
|
||||
}
|
||||
|
||||
override fun addAttribute(attribute: BuildAttribute) {
|
||||
myBuildAttributes.add(attribute)
|
||||
}
|
||||
@@ -55,12 +74,14 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
||||
BuildMetrics(
|
||||
buildTimes = myBuildTimes,
|
||||
buildPerformanceMetrics = myBuildMetrics,
|
||||
buildAttributes = myBuildAttributes
|
||||
buildAttributes = myBuildAttributes,
|
||||
gcMetrics = myGcMetrics
|
||||
)
|
||||
|
||||
override fun addMetrics(metrics: BuildMetrics) {
|
||||
myBuildAttributes.addAll(metrics.buildAttributes)
|
||||
myBuildTimes.addAll(metrics.buildTimes)
|
||||
myBuildMetrics.addAll(metrics.buildPerformanceMetrics)
|
||||
myGcMetrics.addAll(metrics.gcMetrics)
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@ enum class BuildPerformanceMetric(val parent: BuildPerformanceMetric? = null, va
|
||||
DAEMON_INCREASED_MEMORY(readableString = "Increase memory usage", type = ValueType.BYTES),
|
||||
DAEMON_MEMORY_USAGE(readableString = "Total memory usage at the end of build", type = ValueType.BYTES),
|
||||
|
||||
DAEMON_GC_TIME(readableString = "Time spent in GC", type = ValueType.NANOSECONDS),
|
||||
DAEMON_GC_COUNT(readableString = "Count of GC", type = ValueType.NUMBER),
|
||||
|
||||
COMPILE_ITERATION(parent = null, "Total compiler iteration", type = ValueType.NUMBER),
|
||||
ANALYZED_LINES_NUMBER(parent = COMPILE_ITERATION, "Number of lines analyzed", type = ValueType.NUMBER),
|
||||
CODE_GENERATED_LINES_NUMBER(parent = COMPILE_ITERATION, "Number of lines for code generation", type = ValueType.NUMBER),
|
||||
|
||||
+9
@@ -24,6 +24,15 @@ object DoNothingBuildMetricsReporter : BuildMetricsReporter {
|
||||
override fun addAttribute(attribute: BuildAttribute) {
|
||||
}
|
||||
|
||||
override fun addGcMetric(metric: String, value: GcMetric) {
|
||||
}
|
||||
|
||||
override fun startGcMetric(name: String, value: GcMetric) {
|
||||
}
|
||||
|
||||
override fun endGcMetric(name: String, value: GcMetric) {
|
||||
}
|
||||
|
||||
override fun getMetrics(): BuildMetrics =
|
||||
BuildMetrics(
|
||||
BuildTimes(),
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.build.report.metrics
|
||||
|
||||
import java.io.Serializable
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
class GcMetrics : Serializable {
|
||||
|
||||
private val myGcMetrics = HashMap<String, GcMetric>()
|
||||
fun addAll(gcMetrics: GcMetrics) {
|
||||
myGcMetrics.putAll(gcMetrics.myGcMetrics)
|
||||
}
|
||||
|
||||
fun add(metric: String, value: GcMetric) {
|
||||
myGcMetrics[metric] = value
|
||||
}
|
||||
|
||||
fun asGcCountMap(): Map<String, Long> = myGcMetrics.mapValues { it.value.count }
|
||||
fun asGcTimeMap(): Map<String, Long> = myGcMetrics.mapValues { it.value.time }
|
||||
fun asMap(): Map<String, GcMetric> = myGcMetrics
|
||||
}
|
||||
data class GcMetric(
|
||||
val time: Long,
|
||||
val count: Long
|
||||
): Serializable {
|
||||
operator fun minus(increment: GcMetric): GcMetric {
|
||||
return GcMetric(time - increment.time, count - increment.count)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
||||
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
||||
import org.jetbrains.kotlin.build.report.RemoteBuildReporter
|
||||
import org.jetbrains.kotlin.build.report.info
|
||||
import org.jetbrains.kotlin.build.report.metrics.endMeasureGc
|
||||
import org.jetbrains.kotlin.build.report.metrics.startMeasureGc
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
@@ -532,6 +534,7 @@ abstract class CompileServiceImplBase(
|
||||
compilerMessageCollector: MessageCollector,
|
||||
reporter: RemoteBuildReporter
|
||||
): ExitCode {
|
||||
reporter.startMeasureGc()
|
||||
val allKotlinFiles = arrayListOf<File>()
|
||||
val freeArgsWithoutKotlinFiles = arrayListOf<String>()
|
||||
args.freeArgs.forEach {
|
||||
@@ -565,6 +568,7 @@ abstract class CompileServiceImplBase(
|
||||
return try {
|
||||
compiler.compile(allKotlinFiles, args, compilerMessageCollector, changedFiles)
|
||||
} finally {
|
||||
reporter.endMeasureGc()
|
||||
reporter.flush()
|
||||
}
|
||||
}
|
||||
@@ -575,6 +579,7 @@ abstract class CompileServiceImplBase(
|
||||
compilerMessageCollector: MessageCollector,
|
||||
reporter: RemoteBuildReporter
|
||||
): ExitCode {
|
||||
reporter.startMeasureGc()
|
||||
val allKotlinExtensions = (DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS +
|
||||
(incrementalCompilationOptions.kotlinScriptExtensions ?: emptyArray())).distinct()
|
||||
val dotExtensions = allKotlinExtensions.map { ".$it" }
|
||||
@@ -630,6 +635,7 @@ abstract class CompileServiceImplBase(
|
||||
return try {
|
||||
compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot)
|
||||
} finally {
|
||||
reporter.endMeasureGc()
|
||||
reporter.flush()
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -73,6 +73,9 @@ class BuildReportsIT : KGPBaseTest() {
|
||||
//for non-incremental builds
|
||||
assertTrue { report.contains("Build attributes:") }
|
||||
assertTrue { report.contains("REBUILD_REASON:") }
|
||||
//gc metrics
|
||||
assertTrue {report.contains("GC count:")}
|
||||
assertTrue {report.contains("GC time:")}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ data class CompileStatisticsData(
|
||||
//TODO think about it,time in milliseconds
|
||||
val buildTimesMetrics: Map<BuildTime, Long>,
|
||||
val performanceMetrics: Map<BuildPerformanceMetric, Long>,
|
||||
val gcTimeMetrics: Map<String, Long>?,
|
||||
val gcCountMetrics: Map<String, Long>?,
|
||||
val type: String = BuildDataType.TASK_DATA.name
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ internal class TaskRecord(
|
||||
override val buildMetrics: BuildMetrics,
|
||||
override val didWork: Boolean,
|
||||
override val skipMessage: String?,
|
||||
override val icLogLines: List<String>
|
||||
override val icLogLines: List<String>,
|
||||
) : BuildOperationRecord {
|
||||
override val isFromKotlinPlugin: Boolean = classFqName.startsWith("org.jetbrains.kotlin")
|
||||
}
|
||||
|
||||
+17
@@ -85,6 +85,9 @@ internal class PlainTextBuildReportWriter(
|
||||
if (newLineBetweenSections) p.println()
|
||||
|
||||
printBuildAttributes(buildMetrics.buildAttributes)
|
||||
if (newLineBetweenSections) p.println()
|
||||
|
||||
printGcMetrics(buildMetrics.gcMetrics)
|
||||
}
|
||||
|
||||
private fun printBuildTimes(buildTimes: BuildTimes) {
|
||||
@@ -162,6 +165,20 @@ internal class PlainTextBuildReportWriter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun printGcMetrics(gcMetrics: GcMetrics) {
|
||||
val allGcMetrics = gcMetrics.asMap()
|
||||
if (allGcMetrics.isEmpty()) return
|
||||
p.withIndent("GC metrics:") {
|
||||
for (gcMetric in allGcMetrics) {
|
||||
p.println("${gcMetric.key}:")
|
||||
p.withIndent {
|
||||
p.println("GC count: ${gcMetric.value.count}")
|
||||
p.println("GC time: ${gcMetric.value.time}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun printTaskOverview(build: BuildExecutionData) {
|
||||
var allTasksTimeMs = 0L
|
||||
var kotlinTotalTimeMs = 0L
|
||||
|
||||
+3
-1
@@ -81,7 +81,9 @@ internal fun prepareData(
|
||||
kotlinVersion = kotlinVersion,
|
||||
buildUuid = uuid,
|
||||
finishTime = System.currentTimeMillis(),
|
||||
compilerArguments = taskExecutionResult?.taskInfo?.compilerArguments?.asList() ?: emptyList()
|
||||
compilerArguments = taskExecutionResult?.taskInfo?.compilerArguments?.asList() ?: emptyList(),
|
||||
gcCountMetrics = buildMetrics?.gcMetrics?.asGcCountMap(),
|
||||
gcTimeMetrics = buildMetrics?.gcMetrics?.asGcTimeMap()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user