Profiling machinery.
This commit is contained in:
committed by
alexander-gorshenev
parent
3f65eeaeab
commit
c15fb6833d
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.cli.bc
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.profile
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||||
@@ -30,9 +31,6 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
rootDisposable: Disposable
|
rootDisposable: Disposable
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
|
|
||||||
|
|
||||||
configuration.get(KonanConfigKeys.LIBRARY_FILES)?.forEach{ println(it) }
|
|
||||||
|
|
||||||
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
||||||
configuration, Arrays.asList<String>("extensions/common.xml"))
|
configuration, Arrays.asList<String>("extensions/common.xml"))
|
||||||
val project = environment.project
|
val project = environment.project
|
||||||
@@ -101,6 +99,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
put(VERBOSE_PHASES,
|
put(VERBOSE_PHASES,
|
||||||
arguments.verbosePhases.toNonNullList())
|
arguments.verbosePhases.toNonNullList())
|
||||||
put(LIST_PHASES, arguments.listPhases)
|
put(LIST_PHASES, arguments.listPhases)
|
||||||
|
put(TIME_PHASES, arguments.timePhases)
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +109,9 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun main(args: Array<String>) {
|
@JvmStatic fun main(args: Array<String>) {
|
||||||
CLICompiler.doMain(K2Native(), args)
|
profile("Total compiler main()") {
|
||||||
|
CLICompiler.doMain(K2Native(), args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,5 +62,8 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments {
|
|||||||
|
|
||||||
@Argument(value = "list", description = "List all backend phases")
|
@Argument(value = "list", description = "List all backend phases")
|
||||||
public boolean listPhases;
|
public boolean listPhases;
|
||||||
|
|
||||||
|
@Argument(value = "time", description = "Report execution time for compiler phases")
|
||||||
|
public boolean timePhases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -19,11 +19,9 @@ import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
|||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
|
|
||||||
internal final class Context(val config: KonanConfig,
|
internal final class Context(val config: KonanConfig) : KonanBackendContext() {
|
||||||
// TODO: Need to eliminate when deserialization is fixed.
|
|
||||||
val bindingContext: BindingContext,
|
var moduleDescriptor: ModuleDescriptor? = null
|
||||||
val moduleDescriptor: ModuleDescriptor
|
|
||||||
) : KonanBackendContext() {
|
|
||||||
|
|
||||||
var irModule: IrModuleFragment? = null
|
var irModule: IrModuleFragment? = null
|
||||||
set(module: IrModuleFragment?) {
|
set(module: IrModuleFragment?) {
|
||||||
@@ -53,6 +51,7 @@ internal final class Context(val config: KonanConfig,
|
|||||||
lateinit var llvm: Llvm
|
lateinit var llvm: Llvm
|
||||||
|
|
||||||
var phase: KonanPhase? = null
|
var phase: KonanPhase? = null
|
||||||
|
var depth: Int = 0
|
||||||
|
|
||||||
protected fun separator(title: String) {
|
protected fun separator(title: String) {
|
||||||
println("\n\n--- ${title} ----------------------\n")
|
println("\n\n--- ${title} ----------------------\n")
|
||||||
@@ -63,8 +62,9 @@ internal final class Context(val config: KonanConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun printDescriptors() {
|
fun printDescriptors() {
|
||||||
|
if (moduleDescriptor == null) return
|
||||||
separator("Descriptors after: ${phase?.description}")
|
separator("Descriptors after: ${phase?.description}")
|
||||||
moduleDescriptor.deepPrint()
|
moduleDescriptor!!.deepPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyIr() {
|
fun verifyIr() {
|
||||||
@@ -125,6 +125,10 @@ internal final class Context(val config: KonanConfig,
|
|||||||
return config.configuration.getBoolean(KonanConfigKeys.PRINT_BITCODE)
|
return config.configuration.getBoolean(KonanConfigKeys.PRINT_BITCODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shouldProfilePhases(): Boolean {
|
||||||
|
return config.configuration.getBoolean(KonanConfigKeys.TIME_PHASES)
|
||||||
|
}
|
||||||
|
|
||||||
fun log(message: String) {
|
fun log(message: String) {
|
||||||
if (phase?.verbose ?: false) {
|
if (phase?.verbose ?: false) {
|
||||||
println(message)
|
println(message)
|
||||||
|
|||||||
+7
-5
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.profile
|
||||||
import org.jetbrains.kotlin.backend.konan.Distribution
|
import org.jetbrains.kotlin.backend.konan.Distribution
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.loadMetadata
|
import org.jetbrains.kotlin.backend.konan.llvm.loadMetadata
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
@@ -36,14 +37,15 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
for (path in libraries) {
|
for (path in libraries) {
|
||||||
val filePath = File(path)
|
val filePath = File(path)
|
||||||
if (!filePath.exists()) {
|
if (!filePath.exists()) {
|
||||||
error("Path '" + path + "' does not exist");
|
error("Path '" + path + "' does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
val moduleDescriptor = loadMetadata(configuration, filePath);
|
profile("Loading ${filePath}") {
|
||||||
|
val moduleDescriptor = loadMetadata(configuration, filePath)
|
||||||
allMetadata.add(moduleDescriptor);
|
allMetadata.add(moduleDescriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return allMetadata;
|
return allMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val moduleDescriptors: List<ModuleDescriptorImpl> by lazy {
|
internal val moduleDescriptors: List<ModuleDescriptorImpl> by lazy {
|
||||||
|
|||||||
+2
@@ -53,6 +53,8 @@ class KonanConfigKeys {
|
|||||||
= CompilerConfigurationKey.create("verbose backend phases");
|
= CompilerConfigurationKey.create("verbose backend phases");
|
||||||
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
||||||
= CompilerConfigurationKey.create("list backend phases");
|
= CompilerConfigurationKey.create("list backend phases");
|
||||||
|
val TIME_PHASES: CompilerConfigurationKey<Boolean>
|
||||||
|
= CompilerConfigurationKey.create("time backend phases");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
|
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.profile
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
@@ -43,20 +44,22 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn
|
|||||||
|
|
||||||
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
||||||
|
|
||||||
// Build AST and binding info.
|
val context = Context(konanConfig)
|
||||||
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
|
val phaser = PhaseManager(context)
|
||||||
NativeAnalyzer(environment, environment.getSourceFiles(), konanConfig))
|
|
||||||
|
phaser.phase(KonanPhase.FRONTEND) {
|
||||||
|
// Build AST and binding info.
|
||||||
|
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
|
||||||
|
NativeAnalyzer(environment, environment.getSourceFiles(), konanConfig))
|
||||||
|
context.moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
val bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext
|
val bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext
|
||||||
val moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor
|
|
||||||
|
|
||||||
val context = Context(konanConfig, bindingContext, moduleDescriptor)
|
|
||||||
val phaser = PhaseManager(context)
|
|
||||||
|
|
||||||
phaser.phase(KonanPhase.PSI_TO_IR) {
|
phaser.phase(KonanPhase.PSI_TO_IR) {
|
||||||
// Translate AST to high level IR.
|
// Translate AST to high level IR.
|
||||||
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
||||||
val module = translator.generateModule( moduleDescriptor,
|
val module = translator.generateModule( context.moduleDescriptor!!,
|
||||||
environment.getSourceFiles(), bindingContext)
|
environment.getSourceFiles(), bindingContext)
|
||||||
|
|
||||||
context.irModule = module
|
context.irModule = module
|
||||||
|
|||||||
+29
-14
@@ -1,10 +1,12 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.*
|
||||||
|
|
||||||
enum class KonanPhase(val description: String,
|
enum class KonanPhase(val description: String,
|
||||||
var enabled: Boolean = true, var verbose: Boolean = false) {
|
var enabled: Boolean = true, var verbose: Boolean = false) {
|
||||||
|
|
||||||
|
/* */ FRONTEND("Frontend builds AST"),
|
||||||
/* */ PSI_TO_IR("Psi to IR conversion"),
|
/* */ PSI_TO_IR("Psi to IR conversion"),
|
||||||
/* */ BACKEND("All backend"),
|
/* */ BACKEND("All backend"),
|
||||||
/* ... */ LOWER("IR Lowering"),
|
/* ... */ LOWER("IR Lowering"),
|
||||||
@@ -24,19 +26,28 @@ enum class KonanPhase(val description: String,
|
|||||||
object KonanPhases {
|
object KonanPhases {
|
||||||
val phases = KonanPhase.values().associate { it.name.toLowerCase() to it }
|
val phases = KonanPhase.values().associate { it.name.toLowerCase() to it }
|
||||||
|
|
||||||
fun config(config: KonanConfig) {
|
fun known(name: String): String {
|
||||||
val disabled = config.configuration.get(KonanConfigKeys.DISABLED_PHASES)
|
if (phases[name] == null) {
|
||||||
disabled?.forEach { phases[it]!!.enabled = false }
|
error("Unknown phase: $name. Use -list to see the list of phases.")
|
||||||
|
|
||||||
val enabled = config.configuration.get(KonanConfigKeys.ENABLED_PHASES)
|
|
||||||
enabled?.forEach { phases[it]!!.enabled = true }
|
|
||||||
|
|
||||||
val verbose = config.configuration.get(KonanConfigKeys.VERBOSE_PHASES)
|
|
||||||
verbose?.forEach { phases[it]!!.verbose = true }
|
|
||||||
|
|
||||||
if (config.configuration.get(KonanConfigKeys.NOLINK) ?: false ) {
|
|
||||||
KonanPhase.LINKER.enabled = false
|
|
||||||
}
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
fun config(config: KonanConfig) {
|
||||||
|
with (config.configuration) { with (KonanConfigKeys) {
|
||||||
|
val disabled = get(DISABLED_PHASES)
|
||||||
|
disabled?.forEach { phases[known(it)]!!.enabled = false }
|
||||||
|
|
||||||
|
val enabled = get(ENABLED_PHASES)
|
||||||
|
enabled?.forEach { phases[known(it)]!!.enabled = true }
|
||||||
|
|
||||||
|
val verbose = get(VERBOSE_PHASES)
|
||||||
|
verbose?.forEach { phases[known(it)]!!.verbose = true }
|
||||||
|
|
||||||
|
if (get(NOLINK) ?: false ) {
|
||||||
|
KonanPhase.LINKER.enabled = false
|
||||||
|
}
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun list() {
|
fun list() {
|
||||||
@@ -57,10 +68,13 @@ internal class PhaseManager(val context: Context) {
|
|||||||
|
|
||||||
val savePhase = context.phase
|
val savePhase = context.phase
|
||||||
context.phase = phase
|
context.phase = phase
|
||||||
|
context.depth ++
|
||||||
body()
|
|
||||||
|
|
||||||
with (context) {
|
with (context) {
|
||||||
|
profileIf(shouldProfilePhases(), "Phase ${nTabs(depth)} ${phase.name}") {
|
||||||
|
body()
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldVerifyDescriptors()) {
|
if (shouldVerifyDescriptors()) {
|
||||||
verifyDescriptors()
|
verifyDescriptors()
|
||||||
}
|
}
|
||||||
@@ -82,6 +96,7 @@ internal class PhaseManager(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.depth --
|
||||||
context.phase = savePhase
|
context.phase = savePhase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.descriptors
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.nTabs
|
||||||
import org.jetbrains.kotlin.renderer.*
|
import org.jetbrains.kotlin.renderer.*
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -20,7 +21,7 @@ public class DeepPrintVisitor(worker: DeclarationDescriptorVisitor<Boolean, Int>
|
|||||||
public class PrintVisitor: DeclarationDescriptorVisitor<Boolean, Int> {
|
public class PrintVisitor: DeclarationDescriptorVisitor<Boolean, Int> {
|
||||||
|
|
||||||
fun printDescriptor(descriptor: DeclarationDescriptor, amount: Int): Boolean {
|
fun printDescriptor(descriptor: DeclarationDescriptor, amount: Int): Boolean {
|
||||||
println(String.format("%1$-${(amount+1)*4}s", "") + descriptor.toString())
|
println("${nTabs(amount)} ${descriptor.toString()}")
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.konan.util
|
||||||
|
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
fun printMillisec(message: String, body: () -> Unit) {
|
||||||
|
val msec = measureTimeMillis{
|
||||||
|
body()
|
||||||
|
}
|
||||||
|
println("$message: $msec msec")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun profile(message: String, body: () -> Unit) = profileIf(
|
||||||
|
System.getProperty("konan.profile")?.equals("true") ?: false,
|
||||||
|
message, body)
|
||||||
|
|
||||||
|
fun profileIf(condition: Boolean, message: String, body: () -> Unit) =
|
||||||
|
if (condition) printMillisec(message, body) else body()
|
||||||
|
|
||||||
|
fun nTabs(amount: Int): String {
|
||||||
|
return String.format("%1$-${(amount+1)*4}s", "")
|
||||||
|
}
|
||||||
|
|
||||||
+6
-1
@@ -6,7 +6,6 @@ else
|
|||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
fi
|
fi
|
||||||
[ -n "$JAVACMD" ] || JAVACMD=java
|
[ -n "$JAVACMD" ] || JAVACMD=java
|
||||||
[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx256M -Xms32M"
|
|
||||||
|
|
||||||
declare -a java_args
|
declare -a java_args
|
||||||
declare -a konan_args
|
declare -a konan_args
|
||||||
@@ -25,6 +24,12 @@ while [ $# -gt 0 ]; do
|
|||||||
echo "TODO: need to pass arguments to all the tools somehow."
|
echo "TODO: need to pass arguments to all the tools somehow."
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
-time)
|
||||||
|
konan_args=("${konan_args[@]}" -time)
|
||||||
|
java_args=("${java_args[@]}" -agentlib:hprof=cpu=samples -Dkonan.profile=true)
|
||||||
|
JAVACMD="time $JAVACMD"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
konan_args=("${konan_args[@]}" "$1")
|
konan_args=("${konan_args[@]}" "$1")
|
||||||
shift
|
shift
|
||||||
|
|||||||
Reference in New Issue
Block a user