diff --git a/build-common/src/org/jetbrains/kotlin/build/report/metrics/BuildPerformanceMetric.kt b/build-common/src/org/jetbrains/kotlin/build/report/metrics/BuildPerformanceMetric.kt index 5ac12884195..218f1efca4f 100644 --- a/build-common/src/org/jetbrains/kotlin/build/report/metrics/BuildPerformanceMetric.kt +++ b/build-common/src/org/jetbrains/kotlin/build/report/metrics/BuildPerformanceMetric.kt @@ -15,6 +15,9 @@ enum class BuildPerformanceMetric(val parent: BuildPerformanceMetric? = null, va BUNDLE_SIZE(readableString = "Total size of the final bundle", 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), + 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), @@ -39,7 +42,7 @@ enum class BuildPerformanceMetric(val parent: BuildPerformanceMetric? = null, va START_TASK_ACTION_EXECUTION(readableString = "Start time of task action", type = ValueType.MILLISECONDS), CALL_KOTLIN_DAEMON(readableString = "Finish gradle part of task execution", type = ValueType.NANOSECONDS), CALL_WORKER(readableString = "Worker submit time", type = ValueType.NANOSECONDS), - START_WORKER_EXECUTION(readableString = "Start time of werker execution", type = ValueType.NANOSECONDS), + START_WORKER_EXECUTION(readableString = "Start time of worker execution", type = ValueType.NANOSECONDS), START_KOTLIN_DAEMON_EXECUTION(readableString = "Start time of kotlin daemon task execution", type = ValueType.NANOSECONDS), FINISH_KOTLIN_DAEMON_EXECUTION(readableString = "Finish kotlin daemon execution", type = ValueType.MILLISECONDS), ; diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt index 3d7cf601faf..c77a2ecb9f4 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt @@ -81,7 +81,7 @@ interface CompileService : Remote { fun checkCompilerId(expectedCompilerId: CompilerId): Boolean @Throws(RemoteException::class) - fun getUsedMemory(): CallResult + fun getUsedMemory(withGC: Boolean = true): CallResult @Throws(RemoteException::class) fun getDaemonOptions(): CallResult diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index 2d3dc330e16..d3e7c1ae7e1 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -723,8 +723,8 @@ class CompileServiceImpl( (compilerId.compilerClasspath.all { expectedCompilerId.compilerClasspath.contains(it) }) && !classpathWatcher.isChanged - override fun getUsedMemory(): CompileService.CallResult = - ifAlive { CompileService.CallResult.Good(usedMemory(withGC = true)) } + override fun getUsedMemory(withGC: Boolean): CompileService.CallResult = + ifAlive { CompileService.CallResult.Good(usedMemory(withGC = withGC)) } override fun shutdown(): CompileService.CallResult = ifAliveExclusive(minAliveness = Aliveness.LastSession) { shutdownWithDelay() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt index ad97041b973..90012186d4b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerWork.kt @@ -212,6 +212,9 @@ internal class GradleKotlinCompilerWork @Inject constructor( log.debug("Kotlin compile daemon JVM options: ${jvmOpts.get().mappers.flatMap { it.toArgs("-") }}") } } + + val memoryUsageBeforeBuild = daemon.getUsedMemory(withGC = true).takeIf { it.isGood }?.get() + val targetPlatform = when (compilerClassName) { KotlinCompilerClass.JVM -> CompileService.TargetPlatform.JVM KotlinCompilerClass.JS -> CompileService.TargetPlatform.JS @@ -231,6 +234,16 @@ internal class GradleKotlinCompilerWork @Inject constructor( bufferingMessageCollector.flush(messageCollector) throw e } finally { + val memoryUsageAfterBuild = daemon.getUsedMemory(withGC = false).takeIf { it.isGood }?.get() + + if (memoryUsageAfterBuild == null || memoryUsageBeforeBuild == null) { + log.debug("Unable to calculate memory usage") + } else { + metrics.addMetric(BuildPerformanceMetric.DAEMON_INCREASED_MEMORY, memoryUsageAfterBuild - memoryUsageBeforeBuild) + metrics.addMetric(BuildPerformanceMetric.DAEMON_MEMORY_USAGE, memoryUsageAfterBuild) + } + + // todo: can we clear cache on the end of session? // often source of the NoSuchObjectException and UnmarshalException, probably caused by the failed/crashed/exited daemon // TODO: implement a proper logic to avoid remote calls in such cases diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt index 6f7a2016627..c4dd3c7d2a9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt @@ -261,7 +261,7 @@ abstract class BuildReportsService : BuildService "${key.readableString}: ${formatSize(value)}" ValueType.MILLISECONDS -> DATE_FORMATTER.format(value) - else -> "${key.readableString}: $value}" + else -> "${key.readableString}: $value" } } timeData.union(perfData).joinTo(readableString, ",", "Performance: [", "]")