Add compiler performance metrics

WIP
This commit is contained in:
Stanislav Erokhin
2021-07-02 19:35:34 +03:00
committed by nataliya.valtman
parent 64da19cb2d
commit 9becb2c468
13 changed files with 63 additions and 17 deletions
@@ -43,9 +43,9 @@ import java.io.PrintStream
abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
protected abstract val performanceManager: CommonCompilerPerformanceManager
abstract val defaultPerformanceManager: CommonCompilerPerformanceManager
protected open fun createPerformanceManager(arguments: A, services: Services): CommonCompilerPerformanceManager = performanceManager
protected open fun createPerformanceManager(arguments: A, services: Services): CommonCompilerPerformanceManager = defaultPerformanceManager
// Used in CompilerRunnerUtil#invokeExecMethod, in Eclipse plugin (KotlinCLICompiler) and in kotlin-gradle-plugin (GradleCompilerRunner)
fun execAndOutputXml(errStream: PrintStream, services: Services, vararg args: String): ExitCode {
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.cli.common
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.util.PerformanceCounter
import java.io.File
import java.lang.management.GarbageCollectorMXBean
@@ -26,6 +28,7 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
private var irGenerationStart: Long = 0
private var targetDescription: String? = null
private var sourceFiles: List<KtFile>? = null
protected var files: Int? = null
protected var lines: Int? = null
@@ -42,12 +45,19 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
private fun deltaTime(start: Long): Long = PerformanceCounter.currentTime() - start
open fun notifyCompilerInitialized(files: Int, lines: Int, targetDescription: String) {
private fun countLinesOfCode(sourceFiles: List<KtFile>): Int =
sourceFiles.sumBy { sourceFile ->
val text = sourceFile.text
StringUtil.getLineBreakCount(text) + (if (StringUtil.endsWithLineBreak(text)) 0 else 1)
}
open fun notifyCompilerInitialized(sourceFiles: List<KtFile>, targetDescription: String) {
if (!isEnabled) return
recordInitializationTime()
this.files = files
this.lines = lines
this.sourceFiles = sourceFiles
this.files = sourceFiles.size
this.lines = countLinesOfCode(sourceFiles)
this.targetDescription = targetDescription
}
@@ -160,4 +170,12 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
private data class GCData(val name: String, val collectionTime: Long, val collectionCount: Long) {
constructor(bean: GarbageCollectorMXBean) : this(bean.name, bean.collectionTime, bean.collectionCount)
}
fun renderCompilerPerformance(): String {
val relevantMeasurements = getMeasurementResults().filter {
it is CompilerInitializationMeasurement || it is CodeAnalysisMeasurement || it is CodeGenerationMeasurement || it is PerformanceCounterMeasurement
}
return "Compiler perf stats:\n" + relevantMeasurements.joinToString(separator = "\n") { " ${it.render()}" }
}
}
@@ -228,7 +228,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
val sourceFiles = environment.getSourceFiles()
configuration[CLIConfigurationKeys.PERF_MANAGER]?.notifyCompilerInitialized(
sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription
sourceFiles, targetDescription
)
return if (messageCollector.hasErrors()) null else environment
@@ -274,8 +274,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
override val performanceManager: CommonCompilerPerformanceManager
get() = error("Unsupported")
override val defaultPerformanceManager: CommonCompilerPerformanceManager = K2JVMCompilerPerformanceManager()
override fun createPerformanceManager(arguments: K2JVMCompilerArguments, services: Services): CommonCompilerPerformanceManager {
val externalManager = services[CommonCompilerPerformanceManager::class.java]
@@ -39,7 +39,7 @@ import java.io.File
class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
override val performanceManager = K2MetadataCompilerPerformanceManager()
override val defaultPerformanceManager: CommonCompilerPerformanceManager = K2MetadataCompilerPerformanceManager()
override fun createArguments() = K2MetadataCompilerArguments()
@@ -58,6 +58,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
paths: KotlinPaths?
): ExitCode {
val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val performanceManager = configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
val pluginLoadResult = loadPlugins(paths, arguments, configuration)
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
@@ -70,7 +71,8 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
configuration.addJvmClasspathRoots(arguments.classpath!!.split(File.pathSeparatorChar).map(::File))
}
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmProtoBufUtil.DEFAULT_MODULE_NAME)
val moduleName = arguments.moduleName ?: JvmProtoBufUtil.DEFAULT_MODULE_NAME
configuration.put(CommonConfigurationKeys.MODULE_NAME, moduleName)
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
@@ -93,6 +95,9 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
val environment =
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.METADATA_CONFIG_FILES)
val mode = if(arguments.expectActualLinker) "KLib" else "metadata"
performanceManager.notifyCompilerInitialized(environment.getSourceFiles(), "$mode mode for $moduleName module")
if (environment.getSourceFiles().isEmpty()) {
if (arguments.version) {
return ExitCode.OK
@@ -48,20 +48,25 @@ import java.io.File
internal class K2MetadataKlibSerializer(private val metadataVersion: BuiltInsBinaryVersion) {
fun serialize(environment: KotlinCoreEnvironment) {
val configuration = environment.configuration
val performanceManager = configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
val dependencyContainer = KlibMetadataDependencyContainer(
configuration,
LockBasedStorageManager("K2MetadataKlibSerializer")
)
performanceManager.notifyAnalysisStarted()
val analyzer = runCommonAnalysisForSerialization(environment, true, dependencyContainer)
performanceManager.notifyAnalysisFinished()
if (analyzer == null || analyzer.hasErrors()) return
val (_, moduleDescriptor) = analyzer.analysisResult
performanceManager.notifyGenerationStarted()
val destDir = checkNotNull(environment.destDir)
performSerialization(configuration, moduleDescriptor, destDir, environment.project)
performanceManager.notifyGenerationFinished()
}
private fun performSerialization(
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -39,14 +40,20 @@ open class MetadataSerializer(
protected var totalFiles = 0
fun serialize(environment: KotlinCoreEnvironment) {
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
performanceManager.notifyAnalysisStarted()
val analyzer = runCommonAnalysisForSerialization(environment, dependOnOldBuiltIns, dependencyContainer = null)
performanceManager.notifyAnalysisFinished()
if (analyzer == null || analyzer.hasErrors()) return
val (bindingContext, moduleDescriptor) = analyzer.analysisResult
performanceManager.notifyGenerationStarted()
val destDir = checkNotNull(environment.destDir)
performSerialization(environment.getSourceFiles(), bindingContext, moduleDescriptor, destDir, environment.project)
performanceManager.notifyGenerationFinished()
}
protected open fun performSerialization(