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(
|
data class BuildMetrics(
|
||||||
val buildTimes: BuildTimes = BuildTimes(),
|
val buildTimes: BuildTimes = BuildTimes(),
|
||||||
val buildPerformanceMetrics: BuildPerformanceMetrics = BuildPerformanceMetrics(),
|
val buildPerformanceMetrics: BuildPerformanceMetrics = BuildPerformanceMetrics(),
|
||||||
val buildAttributes: BuildAttributes = BuildAttributes()
|
val buildAttributes: BuildAttributes = BuildAttributes(),
|
||||||
|
val gcMetrics: GcMetrics = GcMetrics()
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
fun addAll(other: BuildMetrics) {
|
fun addAll(other: BuildMetrics) {
|
||||||
buildTimes.addAll(other.buildTimes)
|
buildTimes.addAll(other.buildTimes)
|
||||||
buildPerformanceMetrics.addAll(other.buildPerformanceMetrics)
|
buildPerformanceMetrics.addAll(other.buildPerformanceMetrics)
|
||||||
buildAttributes.addAll(other.buildAttributes)
|
buildAttributes.addAll(other.buildAttributes)
|
||||||
|
gcMetrics.addAll(other.gcMetrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.build.report.metrics
|
package org.jetbrains.kotlin.build.report.metrics
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
|
||||||
interface BuildMetricsReporter {
|
interface BuildMetricsReporter {
|
||||||
fun startMeasure(time: BuildTime)
|
fun startMeasure(time: BuildTime)
|
||||||
fun endMeasure(time: BuildTime)
|
fun endMeasure(time: BuildTime)
|
||||||
@@ -14,6 +16,11 @@ interface BuildMetricsReporter {
|
|||||||
fun addMetric(metric: BuildPerformanceMetric, value: Long)
|
fun addMetric(metric: BuildPerformanceMetric, value: Long)
|
||||||
fun addTimeMetric(metric: BuildPerformanceMetric)
|
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 addAttribute(attribute: BuildAttribute)
|
||||||
|
|
||||||
fun getMetrics(): BuildMetrics
|
fun getMetrics(): BuildMetrics
|
||||||
@@ -27,4 +34,17 @@ inline fun <T> BuildMetricsReporter.measure(time: BuildTime, fn: () -> T): T {
|
|||||||
} finally {
|
} finally {
|
||||||
endMeasure(time)
|
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(
|
EnumMap(
|
||||||
BuildTime::class.java
|
BuildTime::class.java
|
||||||
)
|
)
|
||||||
|
private val myGcPerformance = HashMap<String, GcMetric>()
|
||||||
private val myBuildTimes = BuildTimes()
|
private val myBuildTimes = BuildTimes()
|
||||||
private val myBuildMetrics = BuildPerformanceMetrics()
|
private val myBuildMetrics = BuildPerformanceMetrics()
|
||||||
private val myBuildAttributes = BuildAttributes()
|
private val myBuildAttributes = BuildAttributes()
|
||||||
|
private val myGcMetrics = GcMetrics()
|
||||||
|
|
||||||
override fun startMeasure(time: BuildTime) {
|
override fun startMeasure(time: BuildTime) {
|
||||||
if (time in myBuildTimeStartNs) {
|
if (time in myBuildTimeStartNs) {
|
||||||
@@ -30,6 +32,19 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
|||||||
myBuildTimes.addTimeNs(time, durationNs)
|
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) {
|
override fun addTimeMetricNs(time: BuildTime, durationNs: Long) {
|
||||||
myBuildTimes.addTimeNs(time, durationNs)
|
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) {
|
override fun addAttribute(attribute: BuildAttribute) {
|
||||||
myBuildAttributes.add(attribute)
|
myBuildAttributes.add(attribute)
|
||||||
}
|
}
|
||||||
@@ -55,12 +74,14 @@ class BuildMetricsReporterImpl : BuildMetricsReporter, Serializable {
|
|||||||
BuildMetrics(
|
BuildMetrics(
|
||||||
buildTimes = myBuildTimes,
|
buildTimes = myBuildTimes,
|
||||||
buildPerformanceMetrics = myBuildMetrics,
|
buildPerformanceMetrics = myBuildMetrics,
|
||||||
buildAttributes = myBuildAttributes
|
buildAttributes = myBuildAttributes,
|
||||||
|
gcMetrics = myGcMetrics
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun addMetrics(metrics: BuildMetrics) {
|
override fun addMetrics(metrics: BuildMetrics) {
|
||||||
myBuildAttributes.addAll(metrics.buildAttributes)
|
myBuildAttributes.addAll(metrics.buildAttributes)
|
||||||
myBuildTimes.addAll(metrics.buildTimes)
|
myBuildTimes.addAll(metrics.buildTimes)
|
||||||
myBuildMetrics.addAll(metrics.buildPerformanceMetrics)
|
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_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_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),
|
COMPILE_ITERATION(parent = null, "Total compiler iteration", type = ValueType.NUMBER),
|
||||||
ANALYZED_LINES_NUMBER(parent = COMPILE_ITERATION, "Number of lines analyzed", 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),
|
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 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 =
|
override fun getMetrics(): BuildMetrics =
|
||||||
BuildMetrics(
|
BuildMetrics(
|
||||||
BuildTimes(),
|
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.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
||||||
import org.jetbrains.kotlin.build.report.RemoteBuildReporter
|
import org.jetbrains.kotlin.build.report.RemoteBuildReporter
|
||||||
import org.jetbrains.kotlin.build.report.info
|
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.CLICompiler
|
||||||
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
@@ -532,6 +534,7 @@ abstract class CompileServiceImplBase(
|
|||||||
compilerMessageCollector: MessageCollector,
|
compilerMessageCollector: MessageCollector,
|
||||||
reporter: RemoteBuildReporter
|
reporter: RemoteBuildReporter
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
|
reporter.startMeasureGc()
|
||||||
val allKotlinFiles = arrayListOf<File>()
|
val allKotlinFiles = arrayListOf<File>()
|
||||||
val freeArgsWithoutKotlinFiles = arrayListOf<String>()
|
val freeArgsWithoutKotlinFiles = arrayListOf<String>()
|
||||||
args.freeArgs.forEach {
|
args.freeArgs.forEach {
|
||||||
@@ -565,6 +568,7 @@ abstract class CompileServiceImplBase(
|
|||||||
return try {
|
return try {
|
||||||
compiler.compile(allKotlinFiles, args, compilerMessageCollector, changedFiles)
|
compiler.compile(allKotlinFiles, args, compilerMessageCollector, changedFiles)
|
||||||
} finally {
|
} finally {
|
||||||
|
reporter.endMeasureGc()
|
||||||
reporter.flush()
|
reporter.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,6 +579,7 @@ abstract class CompileServiceImplBase(
|
|||||||
compilerMessageCollector: MessageCollector,
|
compilerMessageCollector: MessageCollector,
|
||||||
reporter: RemoteBuildReporter
|
reporter: RemoteBuildReporter
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
|
reporter.startMeasureGc()
|
||||||
val allKotlinExtensions = (DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS +
|
val allKotlinExtensions = (DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS +
|
||||||
(incrementalCompilationOptions.kotlinScriptExtensions ?: emptyArray())).distinct()
|
(incrementalCompilationOptions.kotlinScriptExtensions ?: emptyArray())).distinct()
|
||||||
val dotExtensions = allKotlinExtensions.map { ".$it" }
|
val dotExtensions = allKotlinExtensions.map { ".$it" }
|
||||||
@@ -630,6 +635,7 @@ abstract class CompileServiceImplBase(
|
|||||||
return try {
|
return try {
|
||||||
compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot)
|
compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot)
|
||||||
} finally {
|
} finally {
|
||||||
|
reporter.endMeasureGc()
|
||||||
reporter.flush()
|
reporter.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -73,6 +73,9 @@ class BuildReportsIT : KGPBaseTest() {
|
|||||||
//for non-incremental builds
|
//for non-incremental builds
|
||||||
assertTrue { report.contains("Build attributes:") }
|
assertTrue { report.contains("Build attributes:") }
|
||||||
assertTrue { report.contains("REBUILD_REASON:") }
|
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
|
//TODO think about it,time in milliseconds
|
||||||
val buildTimesMetrics: Map<BuildTime, Long>,
|
val buildTimesMetrics: Map<BuildTime, Long>,
|
||||||
val performanceMetrics: Map<BuildPerformanceMetric, Long>,
|
val performanceMetrics: Map<BuildPerformanceMetric, Long>,
|
||||||
|
val gcTimeMetrics: Map<String, Long>?,
|
||||||
|
val gcCountMetrics: Map<String, Long>?,
|
||||||
val type: String = BuildDataType.TASK_DATA.name
|
val type: String = BuildDataType.TASK_DATA.name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ internal class TaskRecord(
|
|||||||
override val buildMetrics: BuildMetrics,
|
override val buildMetrics: BuildMetrics,
|
||||||
override val didWork: Boolean,
|
override val didWork: Boolean,
|
||||||
override val skipMessage: String?,
|
override val skipMessage: String?,
|
||||||
override val icLogLines: List<String>
|
override val icLogLines: List<String>,
|
||||||
) : BuildOperationRecord {
|
) : BuildOperationRecord {
|
||||||
override val isFromKotlinPlugin: Boolean = classFqName.startsWith("org.jetbrains.kotlin")
|
override val isFromKotlinPlugin: Boolean = classFqName.startsWith("org.jetbrains.kotlin")
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -85,6 +85,9 @@ internal class PlainTextBuildReportWriter(
|
|||||||
if (newLineBetweenSections) p.println()
|
if (newLineBetweenSections) p.println()
|
||||||
|
|
||||||
printBuildAttributes(buildMetrics.buildAttributes)
|
printBuildAttributes(buildMetrics.buildAttributes)
|
||||||
|
if (newLineBetweenSections) p.println()
|
||||||
|
|
||||||
|
printGcMetrics(buildMetrics.gcMetrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun printBuildTimes(buildTimes: BuildTimes) {
|
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) {
|
private fun printTaskOverview(build: BuildExecutionData) {
|
||||||
var allTasksTimeMs = 0L
|
var allTasksTimeMs = 0L
|
||||||
var kotlinTotalTimeMs = 0L
|
var kotlinTotalTimeMs = 0L
|
||||||
|
|||||||
+3
-1
@@ -81,7 +81,9 @@ internal fun prepareData(
|
|||||||
kotlinVersion = kotlinVersion,
|
kotlinVersion = kotlinVersion,
|
||||||
buildUuid = uuid,
|
buildUuid = uuid,
|
||||||
finishTime = System.currentTimeMillis(),
|
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