FIR CLI: count lines/files and report events to perfman

This commit is contained in:
Ilya Chernikov
2022-01-31 18:57:06 +01:00
committed by teamcity
parent 090a451902
commit 973273c6c6
5 changed files with 98 additions and 34 deletions
@@ -58,6 +58,12 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
recordPerfCountersMeasurements() 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() { open fun notifyAnalysisStarted() {
analysisStart = PerformanceCounter.currentTime() analysisStart = PerformanceCounter.currentTime()
} }
@@ -128,19 +128,20 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
// should be called after configuring jdk home from build file // should be called after configuring jdk home from build file
configuration.configureJdkClasspathRoots() 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 */) { if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR) && arguments.useFirLT /* TODO: consider storing in the configuration instead of using args here directly */) {
val projectEnvironment = val projectEnvironment =
createProjectEnvironment(configuration, rootDisposable, EnvironmentConfigFiles.JVM_CONFIG_FILES, messageCollector) createProjectEnvironment(configuration, rootDisposable, EnvironmentConfigFiles.JVM_CONFIG_FILES, messageCollector)
compileModulesUsingFrontendIrAndLightTree( compileModulesUsingFrontendIrAndLightTree(
projectEnvironment, configuration, messageCollector, buildFile, chunk projectEnvironment, configuration, messageCollector, buildFile, chunk, targetDescription
) )
} else { } else {
val environment = createCoreEnvironment( val environment = createCoreEnvironment(
rootDisposable, configuration, messageCollector, rootDisposable, configuration, messageCollector,
chunk.map { input -> input.getModuleName() + "-" + input.getModuleType() }.let { names -> targetDescription
names.singleOrNull() ?: names.joinToString()
}
) ?: return COMPILATION_ERROR ) ?: return COMPILATION_ERROR
environment.registerJavacIfNeeded(arguments).let { environment.registerJavacIfNeeded(arguments).let {
if (!it) return COMPILATION_ERROR if (!it) return COMPILATION_ERROR
@@ -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.JvmGeneratorExtensionsImpl
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys 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.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -82,11 +83,16 @@ fun compileModulesUsingFrontendIrAndLightTree(
compilerConfiguration: CompilerConfiguration, compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector, messageCollector: MessageCollector,
buildFile: File?, buildFile: File?,
chunk: List<Module> chunk: List<Module>,
targetDescription: String
): Boolean { ): Boolean {
require(projectEnvironment is VfsBasedProjectEnvironment) // TODO: abstract away this requirement require(projectEnvironment is VfsBasedProjectEnvironment) // TODO: abstract away this requirement
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val performanceManager = compilerConfiguration[CLIConfigurationKeys.PERF_MANAGER]
performanceManager?.notifyCompilerInitialized(0, 0, targetDescription)
messageCollector.report( messageCollector.report(
CompilerMessageSeverity.STRONG_WARNING, CompilerMessageSeverity.STRONG_WARNING,
"ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir" "ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir"
@@ -120,31 +126,46 @@ fun compileModulesUsingFrontendIrAndLightTree(
moduleConfiguration moduleConfiguration
) )
val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter)
performanceManager?.notifyAnalysisStarted()
val analysisResults = compileModuleToAnalyzedFir( val analysisResults = compileModuleToAnalyzedFir(
compilerInput, compilerInput,
compilerEnvironment, compilerEnvironment,
emptyList(), emptyList(),
null, null,
diagnosticsReporter diagnosticsReporter,
performanceManager
) )
if (diagnosticsReporter.hasErrors) { performanceManager?.notifyAnalysisFinished()
diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)
continue
}
// TODO: consider what to do if many modules has main classes // TODO: consider what to do if many modules has main classes
if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
mainClassFqName = findMainClass(analysisResults.fir) mainClassFqName = findMainClass(analysisResults.fir)
} }
if (diagnosticsReporter.hasErrors) {
diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)
continue
}
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val irInput = convertAnalyzedFirToIr(compilerInput, analysisResults, compilerEnvironment) val irInput = convertAnalyzedFirToIr(compilerInput, analysisResults, compilerEnvironment)
val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment)
performanceManager?.notifyIRTranslationFinished()
val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager)
diagnosticsReporter.reportToMessageCollector( diagnosticsReporter.reportToMessageCollector(
messageCollector, moduleConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) messageCollector, moduleConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
) )
performanceManager?.notifyIRGenerationFinished()
performanceManager?.notifyGenerationFinished()
if (!diagnosticsReporter.hasErrors) { if (!diagnosticsReporter.hasErrors) {
outputs.add(codegenOutput.generationState) outputs.add(codegenOutput.generationState)
} }
@@ -186,7 +207,8 @@ fun convertAnalyzedFirToIr(
fun generateCodeFromIr( fun generateCodeFromIr(
input: ModuleCompilerIrBackendInput, input: ModuleCompilerIrBackendInput,
environment: ModuleCompilerEnvironment environment: ModuleCompilerEnvironment,
performanceManager: CommonCompilerPerformanceManager?
): ModuleCompilerOutput { ): ModuleCompilerOutput {
// IR // IR
val codegenFactory = JvmIrCodegenFactory( val codegenFactory = JvmIrCodegenFactory(
@@ -218,11 +240,16 @@ fun generateCodeFromIr(
environment.diagnosticsReporter environment.diagnosticsReporter
).build() ).build()
performanceManager?.notifyIRLoweringStarted()
generationState.beforeCompile() generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode( codegenFactory.generateModuleInFrontendIRMode(
generationState, input.irModuleFragment, input.symbolTable, input.extensions, generationState, input.irModuleFragment, input.symbolTable, input.extensions,
FirJvmBackendExtension(input.firSession, input.components) FirJvmBackendExtension(input.firSession, input.components)
) ) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
}
CodegenFactory.doCheckCancelled(generationState) CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done() generationState.factory.done()
@@ -234,7 +261,8 @@ fun compileModuleToAnalyzedFir(
environment: ModuleCompilerEnvironment, environment: ModuleCompilerEnvironment,
previousStepsSymbolProviders: List<FirSymbolProvider>, previousStepsSymbolProviders: List<FirSymbolProvider>,
incrementalExcludesScope: AbstractProjectFileSearchScope?, incrementalExcludesScope: AbstractProjectFileSearchScope?,
diagnosticsReporter: DiagnosticReporter diagnosticsReporter: DiagnosticReporter,
performanceManager: CommonCompilerPerformanceManager?
): ModuleCompilerAnalyzedOutput { ): ModuleCompilerAnalyzedOutput {
var sourcesScope = environment.projectEnvironment.getSearchScopeByIoFiles(input.platformSources) //!! var sourcesScope = environment.projectEnvironment.getSearchScopeByIoFiles(input.platformSources) //!!
val sessionProvider = FirProjectSessionProvider() val sessionProvider = FirProjectSessionProvider()
@@ -280,9 +308,11 @@ fun compileModuleToAnalyzedFir(
sourceFriendsDependencies(input.friendFirModules) sourceFriendsDependencies(input.friendFirModules)
} }
val countFilesAndLines = if (performanceManager == null) null else performanceManager::addSourcesStats
// raw fir // raw fir
val commonRawFir = commonSession?.buildFirViaLightTree(input.commonSources, diagnosticsReporter) val commonRawFir = commonSession?.buildFirViaLightTree(input.commonSources, diagnosticsReporter, countFilesAndLines)
val rawFir = session.buildFirViaLightTree(input.platformSources, diagnosticsReporter) val rawFir = session.buildFirViaLightTree(input.platformSources, diagnosticsReporter, countFilesAndLines)
// resolution // resolution
commonSession?.apply { commonSession?.apply {
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir.pipeline 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.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.PsiHandlingMode 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 org.jetbrains.kotlin.psi.KtFile
import java.io.File import java.io.File
fun FirSession.buildFirViaLightTree(files: Collection<File>, diagnosticsReporter: DiagnosticReporter? = null): List<FirFile> { fun FirSession.buildFirViaLightTree(
files: Collection<File>,
diagnosticsReporter: DiagnosticReporter? = null,
reportFilesAndLines: ((Int, Int) -> Unit)? = null
): List<FirFile> {
val firProvider = (firProvider as FirProviderImpl) val firProvider = (firProvider as FirProviderImpl)
val sourcesToPathsMapper = sourcesToPathsMapper val sourcesToPathsMapper = sourcesToPathsMapper
val builder = LightTree2Fir(this, firProvider.kotlinScopeProvider, diagnosticsReporter) val builder = LightTree2Fir(this, firProvider.kotlinScopeProvider, diagnosticsReporter)
return files.map { val shouldCountLines = (reportFilesAndLines != null)
builder.buildFirFile(it).also { firFile -> 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) 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<KtFile>): List<FirFile> { fun FirSession.buildFirFromKtFiles(ktFiles: Collection<KtFile>): List<FirFile> {
@@ -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.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback 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.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.IrMessageCollector 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.modules.ModuleBuilder
import org.jetbrains.kotlin.cli.common.setupCommonArguments import org.jetbrains.kotlin.cli.common.setupCommonArguments
import org.jetbrains.kotlin.cli.jvm.* 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.compiler.pipeline.*
import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
@@ -183,11 +186,16 @@ class IncrementalFirJvmCompilerRunner(
} }
val diagnosticsReporter = DiagnosticReporterFactory.createReporter() val diagnosticsReporter = DiagnosticReporterFactory.createReporter()
val performanceManager = configuration[CLIConfigurationKeys.PERF_MANAGER]
val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter)
performanceManager?.notifyCompilerInitialized(0, 0, "${targetId.name}-${targetId.type}")
// !! main class - maybe from cache? // !! main class - maybe from cache?
var mainClassFqName: FqName? = null var mainClassFqName: FqName? = null
val renderDiagnosticName = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
var incrementalExcludesScope: AbstractProjectFileSearchScope? = null var incrementalExcludesScope: AbstractProjectFileSearchScope? = null
fun firIncrementalCycle(): ModuleCompilerAnalyzedOutput? { fun firIncrementalCycle(): ModuleCompilerAnalyzedOutput? {
@@ -200,15 +208,20 @@ class IncrementalFirJvmCompilerRunner(
configuration configuration
) )
performanceManager?.notifyAnalysisStarted()
val analysisResults = val analysisResults =
compileModuleToAnalyzedFir( compileModuleToAnalyzedFir(
compilerInput, compilerInput,
compilerEnvironment, compilerEnvironment,
emptyList(), emptyList(),
incrementalExcludesScope, incrementalExcludesScope,
diagnosticsReporter diagnosticsReporter,
performanceManager
) )
performanceManager?.notifyAnalysisFinished()
// TODO: consider what to do if many compilations find a main class // TODO: consider what to do if many compilations find a main class
if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
mainClassFqName = findMainClass(analysisResults.fir) mainClassFqName = findMainClass(analysisResults.fir)
@@ -217,11 +230,7 @@ class IncrementalFirJvmCompilerRunner(
allCompiledSources.addAll(dirtySources) allCompiledSources.addAll(dirtySources)
if (diagnosticsReporter.hasErrors) { if (diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector( diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)
diagnosticsReporter,
collector,
configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
)
return null return null
} }
@@ -248,6 +257,9 @@ class IncrementalFirJvmCompilerRunner(
val cycleResult = firIncrementalCycle() ?: return ExitCode.COMPILATION_ERROR to allCompiledSources val cycleResult = firIncrementalCycle() ?: return ExitCode.COMPILATION_ERROR to allCompiledSources
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl(configuration) val extensions = JvmGeneratorExtensionsImpl(configuration)
val irGenerationExtensions = val irGenerationExtensions =
(projectEnvironment as? VfsBasedProjectEnvironment)?.project?.let { IrGenerationExtension.getInstances(it) }.orEmpty() (projectEnvironment as? VfsBasedProjectEnvironment)?.project?.let { IrGenerationExtension.getInstances(it) }.orEmpty()
@@ -267,6 +279,8 @@ class IncrementalFirJvmCompilerRunner(
irGenerationExtensions irGenerationExtensions
) )
performanceManager?.notifyIRTranslationFinished()
val irInput = ModuleCompilerIrBackendInput( val irInput = ModuleCompilerIrBackendInput(
targetId, targetId,
configuration, configuration,
@@ -277,13 +291,12 @@ class IncrementalFirJvmCompilerRunner(
cycleResult.session cycleResult.session
) )
val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment) val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector( performanceManager?.notifyIRGenerationFinished()
diagnosticsReporter, performanceManager?.notifyGenerationFinished()
collector,
configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)
)
writeOutputs( writeOutputs(
projectEnvironment, projectEnvironment,