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