diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt index eccf2cb2111..f690858ab4a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt @@ -58,6 +58,12 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str recordPerfCountersMeasurements() } + open fun addSourcesStats(files: Int, lines: Int) { + if (!isEnabled) return + this.files = this.files?.plus(files) ?: files + this.lines = this.lines?.plus(lines) ?: lines + } + open fun notifyAnalysisStarted() { analysisStart = PerformanceCounter.currentTime() } 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 02b94105caf..d8342cc1466 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -128,19 +128,20 @@ class K2JVMCompiler : CLICompiler() { // should be called after configuring jdk home from build file configuration.configureJdkClasspathRoots() + val targetDescription = chunk.map { input -> input.getModuleName() + "-" + input.getModuleType() }.let { names -> + names.singleOrNull() ?: names.joinToString() + } if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR) && arguments.useFirLT /* TODO: consider storing in the configuration instead of using args here directly */) { val projectEnvironment = createProjectEnvironment(configuration, rootDisposable, EnvironmentConfigFiles.JVM_CONFIG_FILES, messageCollector) compileModulesUsingFrontendIrAndLightTree( - projectEnvironment, configuration, messageCollector, buildFile, chunk + projectEnvironment, configuration, messageCollector, buildFile, chunk, targetDescription ) } else { val environment = createCoreEnvironment( rootDisposable, configuration, messageCollector, - chunk.map { input -> input.getModuleName() + "-" + input.getModuleType() }.let { names -> - names.singleOrNull() ?: names.joinToString() - } + targetDescription ) ?: return COMPILATION_ERROR environment.registerJavacIfNeeded(arguments).let { if (!it) return COMPILATION_ERROR diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt index 276bab17d4e..8f8613c3b08 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -82,11 +83,16 @@ fun compileModulesUsingFrontendIrAndLightTree( compilerConfiguration: CompilerConfiguration, messageCollector: MessageCollector, buildFile: File?, - chunk: List + chunk: List, + targetDescription: String ): Boolean { require(projectEnvironment is VfsBasedProjectEnvironment) // TODO: abstract away this requirement ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() + val performanceManager = compilerConfiguration[CLIConfigurationKeys.PERF_MANAGER] + + performanceManager?.notifyCompilerInitialized(0, 0, targetDescription) + messageCollector.report( CompilerMessageSeverity.STRONG_WARNING, "ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir" @@ -120,31 +126,46 @@ fun compileModulesUsingFrontendIrAndLightTree( moduleConfiguration ) val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) + + performanceManager?.notifyAnalysisStarted() + val analysisResults = compileModuleToAnalyzedFir( compilerInput, compilerEnvironment, emptyList(), null, - diagnosticsReporter + diagnosticsReporter, + performanceManager ) - if (diagnosticsReporter.hasErrors) { - diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName) - continue - } + performanceManager?.notifyAnalysisFinished() // TODO: consider what to do if many modules has main classes if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { mainClassFqName = findMainClass(analysisResults.fir) } + if (diagnosticsReporter.hasErrors) { + diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName) + continue + } + + performanceManager?.notifyGenerationStarted() + performanceManager?.notifyIRTranslationStarted() + val irInput = convertAnalyzedFirToIr(compilerInput, analysisResults, compilerEnvironment) - val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment) + + performanceManager?.notifyIRTranslationFinished() + + val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager) diagnosticsReporter.reportToMessageCollector( messageCollector, moduleConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) ) + performanceManager?.notifyIRGenerationFinished() + performanceManager?.notifyGenerationFinished() + if (!diagnosticsReporter.hasErrors) { outputs.add(codegenOutput.generationState) } @@ -186,7 +207,8 @@ fun convertAnalyzedFirToIr( fun generateCodeFromIr( input: ModuleCompilerIrBackendInput, - environment: ModuleCompilerEnvironment + environment: ModuleCompilerEnvironment, + performanceManager: CommonCompilerPerformanceManager? ): ModuleCompilerOutput { // IR val codegenFactory = JvmIrCodegenFactory( @@ -218,11 +240,16 @@ fun generateCodeFromIr( environment.diagnosticsReporter ).build() + performanceManager?.notifyIRLoweringStarted() + generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( generationState, input.irModuleFragment, input.symbolTable, input.extensions, FirJvmBackendExtension(input.firSession, input.components) - ) + ) { + performanceManager?.notifyIRLoweringFinished() + performanceManager?.notifyIRGenerationStarted() + } CodegenFactory.doCheckCancelled(generationState) generationState.factory.done() @@ -234,7 +261,8 @@ fun compileModuleToAnalyzedFir( environment: ModuleCompilerEnvironment, previousStepsSymbolProviders: List, incrementalExcludesScope: AbstractProjectFileSearchScope?, - diagnosticsReporter: DiagnosticReporter + diagnosticsReporter: DiagnosticReporter, + performanceManager: CommonCompilerPerformanceManager? ): ModuleCompilerAnalyzedOutput { var sourcesScope = environment.projectEnvironment.getSearchScopeByIoFiles(input.platformSources) //!! val sessionProvider = FirProjectSessionProvider() @@ -280,9 +308,11 @@ fun compileModuleToAnalyzedFir( sourceFriendsDependencies(input.friendFirModules) } + val countFilesAndLines = if (performanceManager == null) null else performanceManager::addSourcesStats + // raw fir - val commonRawFir = commonSession?.buildFirViaLightTree(input.commonSources, diagnosticsReporter) - val rawFir = session.buildFirViaLightTree(input.platformSources, diagnosticsReporter) + val commonRawFir = commonSession?.buildFirViaLightTree(input.commonSources, diagnosticsReporter, countFilesAndLines) + val rawFir = session.buildFirViaLightTree(input.platformSources, diagnosticsReporter, countFilesAndLines) // resolution commonSession?.apply { diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt index 04068e9921d..f6f6da4d670 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.fir.pipeline +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.CharsetToolkit import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.builder.PsiHandlingMode @@ -17,16 +19,28 @@ import org.jetbrains.kotlin.fir.session.sourcesToPathsMapper import org.jetbrains.kotlin.psi.KtFile import java.io.File -fun FirSession.buildFirViaLightTree(files: Collection, diagnosticsReporter: DiagnosticReporter? = null): List { +fun FirSession.buildFirViaLightTree( + files: Collection, + diagnosticsReporter: DiagnosticReporter? = null, + reportFilesAndLines: ((Int, Int) -> Unit)? = null +): List { val firProvider = (firProvider as FirProviderImpl) val sourcesToPathsMapper = sourcesToPathsMapper val builder = LightTree2Fir(this, firProvider.kotlinScopeProvider, diagnosticsReporter) - return files.map { - builder.buildFirFile(it).also { firFile -> + val shouldCountLines = (reportFilesAndLines != null) + var linesCount = 0 + val firFiles = files.map { file -> + val code = FileUtil.loadFile(file, CharsetToolkit.UTF8, true /* code below relies on conversion */) + if (shouldCountLines) { + linesCount += code.count { it == '\n' } // assuming converted line separators + } + builder.buildFirFile(code, file.name, file.path).also { firFile -> firProvider.recordFile(firFile) - sourcesToPathsMapper.registerFileSource(firFile.source!!, it.path) + sourcesToPathsMapper.registerFileSource(firFile.source!!, file.path) } } + reportFilesAndLines?.invoke(files.count(), linesCount) + return firFiles } fun FirSession.buildFirFromKtFiles(ktFiles: Collection): List { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt index 782969c2636..71c8c3174ea 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.cli.common.computeKotlinPaths import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback -import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter +import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.common.messages.IrMessageCollector @@ -28,7 +28,10 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.modules.ModuleBuilder import org.jetbrains.kotlin.cli.common.setupCommonArguments import org.jetbrains.kotlin.cli.jvm.* -import org.jetbrains.kotlin.cli.jvm.compiler.* +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.findMainClass +import org.jetbrains.kotlin.cli.jvm.compiler.forAllFiles import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.* import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser @@ -183,11 +186,16 @@ class IncrementalFirJvmCompilerRunner( } val diagnosticsReporter = DiagnosticReporterFactory.createReporter() + val performanceManager = configuration[CLIConfigurationKeys.PERF_MANAGER] val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) + performanceManager?.notifyCompilerInitialized(0, 0, "${targetId.name}-${targetId.type}") + // !! main class - maybe from cache? var mainClassFqName: FqName? = null + val renderDiagnosticName = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) + var incrementalExcludesScope: AbstractProjectFileSearchScope? = null fun firIncrementalCycle(): ModuleCompilerAnalyzedOutput? { @@ -200,15 +208,20 @@ class IncrementalFirJvmCompilerRunner( configuration ) + performanceManager?.notifyAnalysisStarted() + val analysisResults = compileModuleToAnalyzedFir( compilerInput, compilerEnvironment, emptyList(), incrementalExcludesScope, - diagnosticsReporter + diagnosticsReporter, + performanceManager ) + performanceManager?.notifyAnalysisFinished() + // TODO: consider what to do if many compilations find a main class if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { mainClassFqName = findMainClass(analysisResults.fir) @@ -217,11 +230,7 @@ class IncrementalFirJvmCompilerRunner( allCompiledSources.addAll(dirtySources) if (diagnosticsReporter.hasErrors) { - FirDiagnosticsCompilerResultsReporter.reportToMessageCollector( - diagnosticsReporter, - collector, - configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - ) + diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName) return null } @@ -248,6 +257,9 @@ class IncrementalFirJvmCompilerRunner( val cycleResult = firIncrementalCycle() ?: return ExitCode.COMPILATION_ERROR to allCompiledSources + performanceManager?.notifyGenerationStarted() + performanceManager?.notifyIRTranslationStarted() + val extensions = JvmGeneratorExtensionsImpl(configuration) val irGenerationExtensions = (projectEnvironment as? VfsBasedProjectEnvironment)?.project?.let { IrGenerationExtension.getInstances(it) }.orEmpty() @@ -267,6 +279,8 @@ class IncrementalFirJvmCompilerRunner( irGenerationExtensions ) + performanceManager?.notifyIRTranslationFinished() + val irInput = ModuleCompilerIrBackendInput( targetId, configuration, @@ -277,13 +291,12 @@ class IncrementalFirJvmCompilerRunner( cycleResult.session ) - val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment) + val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager) - FirDiagnosticsCompilerResultsReporter.reportToMessageCollector( - diagnosticsReporter, - collector, - configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - ) + performanceManager?.notifyIRGenerationFinished() + performanceManager?.notifyGenerationFinished() + + diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName) writeOutputs( projectEnvironment,