diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index e71f882f154..1696e6c1600 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -150,6 +150,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() { ) var properIeee754Comparisons by FreezableVar(false) + @Argument(value = "-Xreport-perf", description = "Report detailed performance statistics") + var reportPerf: Boolean by FreezableVar(false) + open fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> { return HashMap, Any>().apply { put(AnalysisFlag.skipMetadataVersionCheck, skipMetadataVersionCheck) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index ecf6e127e02..94b241ebec6 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -124,9 +124,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { ) var constructorCallNormalizationMode: String? by FreezableVar(JVMConstructorCallNormalizationMode.DEFAULT.description) - @Argument(value = "-Xreport-perf", description = "Report detailed performance statistics") - var reportPerf: Boolean by FreezableVar(false) - @Argument( value = "-Xbuild-file", deprecatedName = "-module", diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java index a00180d4026..10c3d5fa961 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cli.common; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; -import kotlin.collections.ArraysKt; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,23 +27,23 @@ import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector; import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil; import org.jetbrains.kotlin.cli.common.messages.MessageRenderer; -import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import org.jetbrains.kotlin.cli.jvm.compiler.CompilerJarLocator; -import org.jetbrains.kotlin.config.*; +import org.jetbrains.kotlin.config.CommonConfigurationKeys; +import org.jetbrains.kotlin.config.CommonConfigurationKeysKt; +import org.jetbrains.kotlin.config.CompilerConfiguration; +import org.jetbrains.kotlin.config.Services; import org.jetbrains.kotlin.progress.CompilationCanceledException; import org.jetbrains.kotlin.progress.CompilationCanceledStatus; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.utils.KotlinPaths; import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir; import org.jetbrains.kotlin.utils.PathUtil; -import org.jetbrains.kotlin.utils.StringsKt; import java.io.File; import java.io.PrintStream; -import java.util.List; -import java.util.Map; -import static org.jetbrains.kotlin.cli.common.ExitCode.*; +import static org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR; +import static org.jetbrains.kotlin.cli.common.ExitCode.INTERNAL_ERROR; import static org.jetbrains.kotlin.cli.common.environment.UtilKt.setIdeaIoUseFallback; import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*; @@ -69,11 +68,16 @@ public abstract class CLICompiler extends CLI @NotNull @Override public ExitCode execImpl(@NotNull MessageCollector messageCollector, @NotNull Services services, @NotNull A arguments) { + CommonCompilerPerformanceManager performanceManager = getPerformanceManager(); + if (arguments.getReportPerf()) { + performanceManager.enableCollectingPerformanceStatistics(); + } + GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector, arguments.getAllWarningsAsErrors()); CompilerConfiguration configuration = new CompilerConfiguration(); configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, groupingCollector); - + configuration.put(CLIConfigurationKeys.PERF_MANAGER, performanceManager); try { setupCommonArgumentsAndServices(configuration, arguments, services); setupPlatformSpecificArgumentsAndServices(configuration, arguments, services); @@ -89,6 +93,14 @@ public abstract class CLICompiler extends CLI try { setIdeaIoUseFallback(); ExitCode code = doExecute(arguments, configuration, rootDisposable, paths); + + performanceManager.notifyCompilationFinished(); + if (arguments.getReportPerf()) { + performanceManager.getMeasurementResults().forEach( + it -> configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(INFO, "PERF: " + it.render(), null) + ); + } + return groupingCollector.hasErrors() ? COMPILATION_ERROR : code; } catch (CompilationCanceledException e) { @@ -212,4 +224,7 @@ public abstract class CLICompiler extends CLI @NotNull Disposable rootDisposable, @Nullable KotlinPaths paths ); + + @NotNull + protected abstract CommonCompilerPerformanceManager getPerformanceManager(); } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java index ab682493981..b9ef766c654 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLIConfigurationKeys.java @@ -27,8 +27,8 @@ public class CLIConfigurationKeys { CompilerConfigurationKey.create("message collector"); public static final CompilerConfigurationKey ALLOW_KOTLIN_PACKAGE = CompilerConfigurationKey.create("allow kotlin package"); - public static final CompilerConfigurationKey REPORT_PERF = - CompilerConfigurationKey.create("report performance information"); + public static final CompilerConfigurationKey PERF_MANAGER = + CompilerConfigurationKey.create("performance manager"); // Used in Eclipse plugin (see KotlinCLICompiler) public static final CompilerConfigurationKey INTELLIJ_PLUGIN_ROOT = diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt new file mode 100644 index 00000000000..e4818a629cf --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.cli.common + +import org.jetbrains.kotlin.util.PerformanceCounter +import java.lang.management.ManagementFactory +import java.util.concurrent.TimeUnit + +abstract class CommonCompilerPerformanceManager(private val presentableName: String) { + protected val measurements: MutableList = mutableListOf() + protected var isEnabled: Boolean = false + private var initStartNanos = PerformanceCounter.currentTime() + private var analysisStart: Long = 0 + private var generationStart: Long = 0 + + fun getMeasurementResults(): List = measurements + + fun enableCollectingPerformanceStatistics() { + isEnabled = true + PerformanceCounter.setTimeCounterEnabled(true) + } + + open fun notifyCompilerInitialized() { + if (!isEnabled) return + recordInitializationTime() + } + + open fun notifyCompilationFinished() { + if (!isEnabled) return + recordGcTime() + recordJitCompilationTime() + recordPerfCountersMeasurements() + } + + open fun notifyAnalysisStarted() { + analysisStart = PerformanceCounter.currentTime() + } + + open fun notifyAnalysisFinished(files: Int, lines: Int, additionalDescription: String?) { + val time = PerformanceCounter.currentTime() - analysisStart + measurements += CodeAnalysisMeasurement(files, lines, TimeUnit.NANOSECONDS.toMillis(time), additionalDescription) + } + + open fun notifyGenerationStarted() { + generationStart = PerformanceCounter.currentTime() + } + + open fun notifyGenerationFinished(lines: Int, files: Int, additionalDescription: String) { + val time = PerformanceCounter.currentTime() - generationStart + measurements += CodeGenerationMeasurement(lines, files, TimeUnit.NANOSECONDS.toMillis(time), additionalDescription) + } + + private fun recordGcTime() { + if (!isEnabled) return + + ManagementFactory.getGarbageCollectorMXBeans().forEach { + measurements += GarbageCollectionMeasurement(it.name, it.collectionTime) + } + } + + private fun recordJitCompilationTime() { + if (!isEnabled) return + + val bean = ManagementFactory.getCompilationMXBean() ?: return + measurements += JitCompilationMeasurement(bean.totalCompilationTime) + } + + private fun recordInitializationTime() { + val time = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - initStartNanos) + measurements += CompilerInitializationMeasurement(time) + } + + private fun recordPerfCountersMeasurements() { + PerformanceCounter.report { s -> measurements += PerformanceCounterMeasurement(s) } + } +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt new file mode 100644 index 00000000000..c8548ba8c00 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.cli.common + +interface PerformanceMeasurement { + fun render(): String +} + + +class JitCompilationMeasurement(private val milliseconds: Long) : PerformanceMeasurement { + override fun render(): String = "JIT time is $milliseconds ms" +} + + +class CompilerInitializationMeasurement(private val milliseconds: Long) : PerformanceMeasurement { + override fun render(): String = "INIT: Compiler initialized in $milliseconds ms" +} + + +class CodeAnalysisMeasurement(private val files: Int, val lines: Int, private val milliseconds: Long, private val description: String?) : + PerformanceMeasurement { + + private val speed: Double = lines.toDouble() * 1000 / milliseconds + + override fun render(): String = + "ANALYZE: $files files ($lines lines) ${description ?: ""}in $milliseconds ms - ${"%.3f".format(speed)} loc/s" +} + + +class CodeGenerationMeasurement(private val files: Int, val lines: Int, private val milliseconds: Long, private val description: String?) : + PerformanceMeasurement { + + private val speed: Double = lines.toDouble() * 1000 / milliseconds + + override fun render(): String = + "GENERATE: $files files ($lines lines) ${description}in $milliseconds ms - ${"%.3f".format(speed)} loc/s" +} + + +class GarbageCollectionMeasurement(private val garbageCollectionKind: String, private val milliseconds: Long) : PerformanceMeasurement { + override fun render(): String = "GC time for $garbageCollectionKind is $milliseconds ms" +} + + +class PerformanceCounterMeasurement(private val counterReport: String) : PerformanceMeasurement { + override fun render(): String = counterReport +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java index f87ee0da090..9b9add5fb90 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.backend.common.output.OutputFileCollection; import org.jetbrains.kotlin.cli.common.CLICompiler; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; +import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager; import org.jetbrains.kotlin.cli.common.ExitCode; import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments; import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants; @@ -95,6 +96,8 @@ public class K2JSCompiler extends CLICompiler { doMain(new K2JSCompiler(), args); } + private final K2JSCompilerPerformanceManager performanceManager = new K2JSCompilerPerformanceManager(); + @NotNull @Override public K2JSCompilerArguments createArguments() { @@ -513,6 +516,11 @@ public class K2JSCompiler extends CLICompiler { return commonPath != null ? commonPath.getPath() : "."; } + @NotNull + @Override + protected CommonCompilerPerformanceManager getPerformanceManager() { + return performanceManager; + } private static MainCallParameters createMainCallParameters(String main) { if (K2JsArgumentConstants.NO_CALL.equals(main)) { @@ -528,4 +536,12 @@ public class K2JSCompiler extends CLICompiler { public String executableScriptFileName() { return "kotlinc-js"; } + + private static final class K2JSCompilerPerformanceManager extends CommonCompilerPerformanceManager { + public K2JSCompilerPerformanceManager() { + super("Kotlin to JS Compiler"); + } + } + + } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index fee9cbcf7ca..7cebbd97956 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -18,11 +18,7 @@ package org.jetbrains.kotlin.cli.jvm import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.Disposable -import org.jetbrains.kotlin.cli.common.CLICompiler -import org.jetbrains.kotlin.cli.common.CLICompiler.getLibraryFromHome -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.CLITool -import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.cli.common.* import org.jetbrains.kotlin.cli.common.ExitCode.* import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.* @@ -47,22 +43,21 @@ import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.script.ScriptDefinitionProvider import org.jetbrains.kotlin.script.StandardScriptDefinition -import org.jetbrains.kotlin.util.PerformanceCounter import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.PathUtil import java.io.File -import java.lang.management.ManagementFactory -import java.util.concurrent.TimeUnit +import java.util.* class K2JVMCompiler : CLICompiler() { + + private val performanceManager: K2JVMCompilerPerformanceManager = K2JVMCompilerPerformanceManager() + override fun doExecute( arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration, rootDisposable: Disposable, paths: KotlinPaths? ): ExitCode { - PerformanceCounter.setTimeCounterEnabled(arguments.reportPerf) - val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) configureJdkHome(arguments, configuration, messageCollector).let { @@ -208,12 +203,7 @@ class K2JVMCompiler : CLICompiler() { if (!it) return COMPILATION_ERROR } } - - if (arguments.reportPerf) { - reportGCTime(configuration) - reportCompilationTime(configuration) - PerformanceCounter.report { s -> reportPerf(configuration, s) } - } + return OK } catch (e: CompilationException) { messageCollector.report( @@ -225,6 +215,8 @@ class K2JVMCompiler : CLICompiler() { } } + override fun getPerformanceManager(): CommonCompilerPerformanceManager = performanceManager + private fun loadPlugins(paths: KotlinPaths?, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode { val pluginClasspaths = arguments.pluginClasspaths?.toMutableList() ?: ArrayList() val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList() @@ -300,11 +292,7 @@ class K2JVMCompiler : CLICompiler() { val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) - if (initStartNanos != 0L) { - val initNanos = System.nanoTime() - initStartNanos - reportPerf(configuration, "INIT: Compiler initialized in " + TimeUnit.NANOSECONDS.toMillis(initNanos) + " ms") - initStartNanos = 0L - } + performanceManager.notifyCompilerInitialized() return if (messageCollector.hasErrors()) null else environment } @@ -343,31 +331,14 @@ class K2JVMCompiler : CLICompiler() { override fun executableScriptFileName(): String = "kotlinc-jvm" - companion object { - private var initStartNanos = System.nanoTime() + private class K2JVMCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to JVM Compiler") + companion object { @JvmStatic fun main(args: Array) { CLITool.doMain(K2JVMCompiler(), args) } - fun reportPerf(configuration: CompilerConfiguration, message: String) { - if (!configuration.getBoolean(CLIConfigurationKeys.REPORT_PERF)) return - - configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(INFO, "PERF: $message") - } - - fun reportGCTime(configuration: CompilerConfiguration) { - ManagementFactory.getGarbageCollectorMXBeans().forEach { - reportPerf(configuration, "GC time for ${it.name} is ${it.collectionTime} ms") - } - } - - fun reportCompilationTime(configuration: CompilerConfiguration) { - val bean = ManagementFactory.getCompilationMXBean() ?: return - reportPerf(configuration, "JIT time is ${bean.totalCompilationTime} ms") - } - private fun putAdvancedOptions(configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments) { configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions) configuration.put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions) @@ -403,7 +374,6 @@ class K2JVMCompiler : CLICompiler() { } configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) - configuration.put(CLIConfigurationKeys.REPORT_PERF, arguments.reportPerf) configuration.put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule) configuration.put(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, arguments.addCompilerBuiltIns) configuration.put(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, arguments.loadBuiltInsFromDependencies) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 733dd8e8855..5386931cdb4 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -29,16 +29,13 @@ import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics import org.jetbrains.kotlin.backend.common.output.OutputFileCollection import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage +import org.jetbrains.kotlin.cli.common.* import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll -import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.state.GenerationState @@ -356,7 +353,10 @@ object KotlinToJVMBytecodeCompiler { val sourceFiles = environment.getSourceFiles() val collector = environment.messageCollector - val analysisStart = PerformanceCounter.currentTime() + // Can be null for Scripts/REPL + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyAnalysisStarted() + val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings) analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { val project = environment.project @@ -377,16 +377,7 @@ object KotlinToJVMBytecodeCompiler { ) } - val analysisNanos = PerformanceCounter.currentTime() - analysisStart - - val sourceLinesOfCode = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(analysisNanos) - val speed = sourceLinesOfCode.toFloat() * 1000 / time - - val message = "ANALYZE: ${sourceFiles.size} files ($sourceLinesOfCode lines) ${targetDescription ?: ""}" + - "in $time ms - ${"%.3f".format(speed)} loc/s" - - K2JVMCompiler.reportPerf(environment.configuration, message) + performanceManager?.notifyAnalysisFinished(sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription) val analysisResult = analyzerWithCompilerReport.analysisResult @@ -445,19 +436,17 @@ object KotlinToJVMBytecodeCompiler { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val generationStart = PerformanceCounter.currentTime() + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyGenerationStarted() KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - val generationNanos = PerformanceCounter.currentTime() - generationStart - val desc = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" - val numberOfSourceFiles = sourceFiles.size - val numberOfLines = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(generationNanos) - val speed = numberOfLines.toFloat() * 1000 / time - val message = "GENERATE: $numberOfSourceFiles files ($numberOfLines lines) ${desc}in $time ms - ${"%.3f".format(speed)} loc/s" + performanceManager?.notifyGenerationFinished( + sourceFiles.size, + environment.countLinesOfCode(sourceFiles), + additionalDescription = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" + ) - K2JVMCompiler.reportPerf(environment.configuration, message) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() AnalyzerWithCompilerReport.reportDiagnostics( diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 index e2ac08cdc55..ea92dca9c3a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 @@ -355,7 +355,10 @@ object KotlinToJVMBytecodeCompiler { val sourceFiles = environment.getSourceFiles() val collector = environment.messageCollector - val analysisStart = PerformanceCounter.currentTime() + // Can be null for Scripts/REPL + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyAnalysisStarted() + val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings) analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { val project = environment.project @@ -376,16 +379,7 @@ object KotlinToJVMBytecodeCompiler { ) } - val analysisNanos = PerformanceCounter.currentTime() - analysisStart - - val sourceLinesOfCode = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(analysisNanos) - val speed = sourceLinesOfCode.toFloat() * 1000 / time - - val message = "ANALYZE: ${sourceFiles.size} files ($sourceLinesOfCode lines) ${targetDescription ?: ""}" + - "in $time ms - ${"%.3f".format(speed)} loc/s" - - K2JVMCompiler.reportPerf(environment.configuration, message) + performanceManager?.notifyAnalysisFinished(sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription) val analysisResult = analyzerWithCompilerReport.analysisResult @@ -444,19 +438,17 @@ object KotlinToJVMBytecodeCompiler { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val generationStart = PerformanceCounter.currentTime() + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyGenerationStarted() KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - val generationNanos = PerformanceCounter.currentTime() - generationStart - val desc = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" - val numberOfSourceFiles = sourceFiles.size - val numberOfLines = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(generationNanos) - val speed = numberOfLines.toFloat() * 1000 / time - val message = "GENERATE: $numberOfSourceFiles files ($numberOfLines lines) ${desc}in $time ms - ${"%.3f".format(speed)} loc/s" + performanceManager?.notifyGenerationFinished( + sourceFiles.size, + environment.countLinesOfCode(sourceFiles), + additionalDescription = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" + ) - K2JVMCompiler.reportPerf(environment.configuration, message) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() AnalyzerWithCompilerReport.reportDiagnostics( diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 index e2ac08cdc55..ea92dca9c3a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 @@ -355,7 +355,10 @@ object KotlinToJVMBytecodeCompiler { val sourceFiles = environment.getSourceFiles() val collector = environment.messageCollector - val analysisStart = PerformanceCounter.currentTime() + // Can be null for Scripts/REPL + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyAnalysisStarted() + val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings) analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { val project = environment.project @@ -376,16 +379,7 @@ object KotlinToJVMBytecodeCompiler { ) } - val analysisNanos = PerformanceCounter.currentTime() - analysisStart - - val sourceLinesOfCode = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(analysisNanos) - val speed = sourceLinesOfCode.toFloat() * 1000 / time - - val message = "ANALYZE: ${sourceFiles.size} files ($sourceLinesOfCode lines) ${targetDescription ?: ""}" + - "in $time ms - ${"%.3f".format(speed)} loc/s" - - K2JVMCompiler.reportPerf(environment.configuration, message) + performanceManager?.notifyAnalysisFinished(sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription) val analysisResult = analyzerWithCompilerReport.analysisResult @@ -444,19 +438,17 @@ object KotlinToJVMBytecodeCompiler { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val generationStart = PerformanceCounter.currentTime() + val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + performanceManager?.notifyGenerationStarted() KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - val generationNanos = PerformanceCounter.currentTime() - generationStart - val desc = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" - val numberOfSourceFiles = sourceFiles.size - val numberOfLines = environment.countLinesOfCode(sourceFiles) - val time = TimeUnit.NANOSECONDS.toMillis(generationNanos) - val speed = numberOfLines.toFloat() * 1000 / time - val message = "GENERATE: $numberOfSourceFiles files ($numberOfLines lines) ${desc}in $time ms - ${"%.3f".format(speed)} loc/s" + performanceManager?.notifyGenerationFinished( + sourceFiles.size, + environment.countLinesOfCode(sourceFiles), + additionalDescription = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" + ) - K2JVMCompiler.reportPerf(environment.configuration, message) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() AnalyzerWithCompilerReport.reportDiagnostics( diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt index cc2a9c6a69a..bd6a3a49cca 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.metadata import com.intellij.openapi.Disposable import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* @@ -38,6 +39,8 @@ import org.jetbrains.kotlin.utils.KotlinPaths import java.io.File class K2MetadataCompiler : CLICompiler() { + private val performanceManager: K2MetadataCompilerPerformanceManager = K2MetadataCompilerPerformanceManager() + override fun createArguments() = K2MetadataCompilerArguments() override fun setupPlatformSpecificArgumentsAndServices( @@ -99,10 +102,14 @@ class K2MetadataCompiler : CLICompiler() { // TODO: update this once a launcher script for K2MetadataCompiler is available override fun executableScriptFileName(): String = "kotlinc" + override fun getPerformanceManager(): CommonCompilerPerformanceManager = performanceManager + companion object { @JvmStatic fun main(args: Array) { doMain(K2MetadataCompiler(), args) } } -} + + private class K2MetadataCompilerPerformanceManager : CommonCompilerPerformanceManager("Kotlin to Metadata compiler") +} \ No newline at end of file diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index b143d6441f3..12fb8f20c07 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -18,6 +18,7 @@ where advanced options include: -Xproper-ieee754-comparisons Generate proper IEEE 754 comparisons in all cases if values are statically known to be of primitive numeric types -Xread-deserialized-contracts Enable reading of contracts from metadata -Xreport-output-files Report source to output files mapping + -Xreport-perf Report detailed performance statistics -Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes) -Xuse-experimental= Enable usages of COMPILATION-affecting experimental API for marker annotation with the given fully qualified name diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 411ed78c232..030915177f3 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -32,7 +32,6 @@ where advanced options include: -Xno-optimize Disable optimizations -Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java -Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types - -Xreport-perf Report detailed performance statistics -Xscript-resolver-environment= Script resolver environment in key-value pairs (the value could be quoted and escaped) -Xsingle-module Combine modules for source files and binary dependencies into a single module @@ -60,6 +59,7 @@ where advanced options include: -Xproper-ieee754-comparisons Generate proper IEEE 754 comparisons in all cases if values are statically known to be of primitive numeric types -Xread-deserialized-contracts Enable reading of contracts from metadata -Xreport-output-files Report source to output files mapping + -Xreport-perf Report detailed performance statistics -Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes) -Xuse-experimental= Enable usages of COMPILATION-affecting experimental API for marker annotation with the given fully qualified name