performance counters infrastructure
This commit is contained in:
+3
@@ -66,6 +66,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
|
|||||||
@Argument(value = "Xno-optimize", description = "Disable optimizations")
|
@Argument(value = "Xno-optimize", description = "Disable optimizations")
|
||||||
public boolean noOptimize;
|
public boolean noOptimize;
|
||||||
|
|
||||||
|
@Argument(value = "Xreport-perf", description = "Report detailed performance statistics")
|
||||||
|
public boolean reportPerf;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String executableScriptFileName() {
|
public String executableScriptFileName() {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.cli.jvm;
|
|||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
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;
|
||||||
@@ -37,6 +39,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration;
|
|||||||
import org.jetbrains.kotlin.config.Services;
|
import org.jetbrains.kotlin.config.Services;
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCacheProvider;
|
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCacheProvider;
|
||||||
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter;
|
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter;
|
||||||
|
import org.jetbrains.kotlin.util.PerformanceCounter;
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||||
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir;
|
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir;
|
||||||
import org.jetbrains.kotlin.utils.PathUtil;
|
import org.jetbrains.kotlin.utils.PathUtil;
|
||||||
@@ -44,14 +47,17 @@ import org.jetbrains.kotlin.utils.PathUtil;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static com.google.common.base.Predicates.in;
|
import static com.google.common.base.Predicates.in;
|
||||||
import static org.jetbrains.kotlin.cli.common.ExitCode.*;
|
import static org.jetbrains.kotlin.cli.common.ExitCode.*;
|
||||||
import static org.jetbrains.kotlin.cli.jvm.config.ConfigPackage.*;
|
import static org.jetbrains.kotlin.cli.jvm.config.ConfigPackage.addJavaSourceRoot;
|
||||||
|
import static org.jetbrains.kotlin.cli.jvm.config.ConfigPackage.addJvmClasspathRoots;
|
||||||
import static org.jetbrains.kotlin.config.ConfigPackage.addKotlinSourceRoot;
|
import static org.jetbrains.kotlin.config.ConfigPackage.addKotlinSourceRoot;
|
||||||
|
|
||||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||||
public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||||
|
private final long initStartNanos = System.nanoTime();
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
doMain(new K2JVMCompiler(), args);
|
doMain(new K2JVMCompiler(), args);
|
||||||
@@ -72,7 +78,7 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
|||||||
messageCollector.report(CompilerMessageSeverity.LOGGING,
|
messageCollector.report(CompilerMessageSeverity.LOGGING,
|
||||||
"Using Kotlin home directory " + paths.getHomePath(), CompilerMessageLocation.NO_LOCATION);
|
"Using Kotlin home directory " + paths.getHomePath(), CompilerMessageLocation.NO_LOCATION);
|
||||||
|
|
||||||
CompilerConfiguration configuration = new CompilerConfiguration();
|
final CompilerConfiguration configuration = new CompilerConfiguration();
|
||||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector);
|
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector);
|
||||||
|
|
||||||
IncrementalCacheProvider incrementalCacheProvider = services.get(IncrementalCacheProvider.class);
|
IncrementalCacheProvider incrementalCacheProvider = services.get(IncrementalCacheProvider.class);
|
||||||
@@ -163,6 +169,7 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
|||||||
jar = null;
|
jar = null;
|
||||||
outputDir = null;
|
outputDir = null;
|
||||||
}
|
}
|
||||||
|
final KotlinCoreEnvironment environment;
|
||||||
|
|
||||||
if (arguments.module != null) {
|
if (arguments.module != null) {
|
||||||
MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector, in(CompilerMessageSeverity.VERBOSE));
|
MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector, in(CompilerMessageSeverity.VERBOSE));
|
||||||
@@ -175,21 +182,33 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File directory = new File(arguments.module).getAbsoluteFile().getParentFile();
|
File directory = new File(arguments.module).getAbsoluteFile().getParentFile();
|
||||||
|
|
||||||
|
CompilerConfiguration compilerConfiguration = KotlinToJVMBytecodeCompiler
|
||||||
|
.createCompilerConfiguration(configuration, moduleScript.getModules(), directory);
|
||||||
|
environment = createCoreEnvironment(rootDisposable, compilerConfiguration);
|
||||||
|
|
||||||
KotlinToJVMBytecodeCompiler.compileModules(
|
KotlinToJVMBytecodeCompiler.compileModules(
|
||||||
configuration, moduleScript.getModules(), directory, jar, arguments.includeRuntime
|
environment, configuration, moduleScript.getModules(), directory, jar, arguments.includeRuntime);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (arguments.script) {
|
else if (arguments.script) {
|
||||||
List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size());
|
List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size());
|
||||||
KotlinCoreEnvironment environment =
|
environment = createCoreEnvironment(rootDisposable, configuration);
|
||||||
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
|
||||||
KotlinToJVMBytecodeCompiler.compileAndExecuteScript(configuration, paths, environment, scriptArgs);
|
KotlinToJVMBytecodeCompiler.compileAndExecuteScript(configuration, paths, environment, scriptArgs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
KotlinCoreEnvironment environment =
|
environment = createCoreEnvironment(rootDisposable, configuration);
|
||||||
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
|
||||||
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime);
|
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arguments.reportPerf) {
|
||||||
|
PerformanceCounter.Companion.report(new Function1<String, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String s) {
|
||||||
|
reportPerf(environment.getConfiguration(), s);
|
||||||
|
return Unit.INSTANCE$;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
catch (CompilationException e) {
|
catch (CompilationException e) {
|
||||||
@@ -199,6 +218,23 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KotlinCoreEnvironment createCoreEnvironment(
|
||||||
|
@NotNull Disposable rootDisposable,
|
||||||
|
@NotNull CompilerConfiguration configuration) {
|
||||||
|
KotlinCoreEnvironment result = KotlinCoreEnvironment.createForProduction(
|
||||||
|
rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||||
|
|
||||||
|
long initNanos = System.nanoTime() - initStartNanos;
|
||||||
|
reportPerf(configuration, "Compiler initialized in " + TimeUnit.NANOSECONDS.toMillis(initNanos) + " ms");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reportPerf(CompilerConfiguration configuration, String message) {
|
||||||
|
MessageCollector collector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
|
||||||
|
assert collector != null;
|
||||||
|
collector.report(CompilerMessageSeverity.INFO, "PERF: " + message, CompilerMessageLocation.NO_LOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
private static void putAdvancedOptions(@NotNull CompilerConfiguration configuration, @NotNull K2JVMCompilerArguments arguments) {
|
private static void putAdvancedOptions(@NotNull CompilerConfiguration configuration, @NotNull K2JVMCompilerArguments arguments) {
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions);
|
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions);
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions);
|
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions);
|
||||||
|
|||||||
+24
-16
@@ -29,12 +29,14 @@ import com.intellij.psi.search.GlobalSearchScope
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
|
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
|
||||||
|
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
||||||
: CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
|
: CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
|
||||||
|
|
||||||
|
private val perfCounter = PerformanceCounter("Find Java class")
|
||||||
private var index: JvmDependenciesIndex by Delegates.notNull()
|
private var index: JvmDependenciesIndex by Delegates.notNull()
|
||||||
|
|
||||||
public fun initIndex(packagesCache: JvmDependenciesIndex) {
|
public fun initIndex(packagesCache: JvmDependenciesIndex) {
|
||||||
@@ -42,9 +44,11 @@ public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? {
|
public override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? {
|
||||||
val classNameWithInnerClasses = classId.getRelativeClassName().asString()
|
return perfCounter.time {
|
||||||
return index.findClass(classId) { dir, type ->
|
val classNameWithInnerClasses = classId.getRelativeClassName().asString()
|
||||||
findClassGivenPackage(searchScope, dir, classNameWithInnerClasses, type)
|
index.findClass(classId) { dir, type ->
|
||||||
|
findClassGivenPackage(searchScope, dir, classNameWithInnerClasses, type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,22 +62,26 @@ public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
||||||
val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return super<CoreJavaFileManager>.findClasses(qName, scope)
|
return perfCounter.time {
|
||||||
|
val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return@time super<CoreJavaFileManager>.findClasses(qName, scope)
|
||||||
|
|
||||||
val result = ArrayList<PsiClass>()
|
val result = ArrayList<PsiClass>()
|
||||||
val classNameWithInnerClasses = classIdAsTopLevelClass.getRelativeClassName().asString()
|
val classNameWithInnerClasses = classIdAsTopLevelClass.getRelativeClassName().asString()
|
||||||
index.traverseDirectoriesInPackage(classIdAsTopLevelClass.getPackageFqName()) { dir, rootType ->
|
index.traverseDirectoriesInPackage(classIdAsTopLevelClass.getPackageFqName()) { dir, rootType ->
|
||||||
val psiClass = findClassGivenPackage(scope, dir, classNameWithInnerClasses, rootType)
|
val psiClass = findClassGivenPackage(scope, dir, classNameWithInnerClasses, rootType)
|
||||||
if (psiClass != null) {
|
if (psiClass != null) {
|
||||||
result.add(psiClass)
|
result.add(psiClass)
|
||||||
|
}
|
||||||
|
// traverse all
|
||||||
|
true
|
||||||
|
}
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
super<CoreJavaFileManager>.findClasses(qName, scope)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.toTypedArray()
|
||||||
}
|
}
|
||||||
// traverse all
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
if (result.isEmpty()) {
|
|
||||||
return super<CoreJavaFileManager>.findClasses(qName, scope)
|
|
||||||
}
|
|
||||||
return result.toArray<PsiClass>(arrayOfNulls<PsiClass>(result.size()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findPackage(packageName: String): PsiPackage? {
|
override fun findPackage(packageName: String): PsiPackage? {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.intellij.openapi.fileTypes.PlainTextFileType
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.FileContextProvider
|
import com.intellij.psi.FileContextProvider
|
||||||
import com.intellij.psi.PsiElementFinder
|
import com.intellij.psi.PsiElementFinder
|
||||||
@@ -86,6 +87,7 @@ import java.io.File
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
import kotlin.platform.platformStatic
|
import kotlin.platform.platformStatic
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
public class KotlinCoreEnvironment private(
|
public class KotlinCoreEnvironment private(
|
||||||
parentDisposable: Disposable,
|
parentDisposable: Disposable,
|
||||||
@@ -157,6 +159,14 @@ public class KotlinCoreEnvironment private(
|
|||||||
public val project: Project
|
public val project: Project
|
||||||
get() = projectEnvironment.getProject()
|
get() = projectEnvironment.getProject()
|
||||||
|
|
||||||
|
public val sourceLinesOfCode: Int by Delegates.lazy { countLinesOfCode(sourceFiles) }
|
||||||
|
|
||||||
|
public fun countLinesOfCode(sourceFiles: List<JetFile>): Int =
|
||||||
|
sourceFiles.sumBy {
|
||||||
|
val text = it.getText()
|
||||||
|
StringUtil.getLineBreakCount(it.getText()) + (if (StringUtil.endsWithLineBreak(text)) 0 else 1)
|
||||||
|
}
|
||||||
|
|
||||||
private fun addExternalAnnotationsRoot(path: File) {
|
private fun addExternalAnnotationsRoot(path: File) {
|
||||||
if (!path.exists()) {
|
if (!path.exists()) {
|
||||||
report(WARNING, "Annotations path entry points to a non-existent location: " + path)
|
report(WARNING, "Annotations path entry points to a non-existent location: " + path)
|
||||||
|
|||||||
+36
-35
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.openapi.Disposable;
|
|
||||||
import com.intellij.openapi.util.Disposer;
|
|
||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
@@ -35,6 +33,7 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport;
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||||
import org.jetbrains.kotlin.cli.common.modules.Module;
|
import org.jetbrains.kotlin.cli.common.modules.Module;
|
||||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsPackage;
|
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsPackage;
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler;
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys;
|
import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
@@ -55,6 +54,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext;
|
|||||||
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
|
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
|
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
|
||||||
|
import org.jetbrains.kotlin.util.PerformanceCounter;
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -64,6 +64,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.cli.jvm.config.ConfigPackage.*;
|
import static org.jetbrains.kotlin.cli.jvm.config.ConfigPackage.*;
|
||||||
import static org.jetbrains.kotlin.config.ConfigPackage.addKotlinSourceRoots;
|
import static org.jetbrains.kotlin.config.ConfigPackage.addKotlinSourceRoots;
|
||||||
@@ -110,6 +111,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean compileModules(
|
public static boolean compileModules(
|
||||||
|
@NotNull KotlinCoreEnvironment environment,
|
||||||
@NotNull CompilerConfiguration configuration,
|
@NotNull CompilerConfiguration configuration,
|
||||||
@NotNull List<Module> chunk,
|
@NotNull List<Module> chunk,
|
||||||
@NotNull File directory,
|
@NotNull File directory,
|
||||||
@@ -118,39 +120,25 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
) {
|
) {
|
||||||
Map<Module, ClassFileFactory> outputFiles = Maps.newHashMap();
|
Map<Module, ClassFileFactory> outputFiles = Maps.newHashMap();
|
||||||
|
|
||||||
CompilerConfiguration compilerConfiguration = createCompilerConfiguration(configuration, chunk, directory);
|
AnalysisResult result = analyze(environment);
|
||||||
|
if (result == null) {
|
||||||
Disposable parentDisposable = Disposer.newDisposable();
|
return false;
|
||||||
KotlinCoreEnvironment environment = null;
|
|
||||||
try {
|
|
||||||
environment = KotlinCoreEnvironment
|
|
||||||
.createForProduction(parentDisposable, compilerConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
|
||||||
|
|
||||||
AnalysisResult result = analyze(environment);
|
|
||||||
if (result == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.throwIfError();
|
|
||||||
|
|
||||||
for (Module module : chunk) {
|
|
||||||
List<JetFile> jetFiles = CompileEnvironmentUtil.getJetFiles(
|
|
||||||
environment.getProject(), getAbsolutePaths(directory, module), new Function1<String, Unit>() {
|
|
||||||
@Override
|
|
||||||
public Unit invoke(String s) {
|
|
||||||
throw new IllegalStateException("Should have been checked before: " + s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
GenerationState generationState =
|
|
||||||
generate(environment, result, jetFiles, module.getModuleName(), new File(module.getOutputDirectory()));
|
|
||||||
outputFiles.put(module, generationState.getFactory());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
if (environment != null) {
|
result.throwIfError();
|
||||||
Disposer.dispose(parentDisposable);
|
|
||||||
}
|
for (Module module : chunk) {
|
||||||
|
List<JetFile> jetFiles = CompileEnvironmentUtil.getJetFiles(
|
||||||
|
environment.getProject(), getAbsolutePaths(directory, module), new Function1<String, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String s) {
|
||||||
|
throw new IllegalStateException("Should have been checked before: " + s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
GenerationState generationState =
|
||||||
|
generate(environment, result, jetFiles, module.getModuleName(), new File(module.getOutputDirectory()));
|
||||||
|
outputFiles.put(module, generationState.getFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Module module : chunk) {
|
for (Module module : chunk) {
|
||||||
@@ -160,7 +148,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static CompilerConfiguration createCompilerConfiguration(
|
public static CompilerConfiguration createCompilerConfiguration(
|
||||||
@NotNull CompilerConfiguration base,
|
@NotNull CompilerConfiguration base,
|
||||||
@NotNull List<Module> chunk,
|
@NotNull List<Module> chunk,
|
||||||
@NotNull File directory
|
@NotNull File directory
|
||||||
@@ -309,6 +297,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
MessageCollector collector = environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
|
MessageCollector collector = environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
|
||||||
assert collector != null;
|
assert collector != null;
|
||||||
|
|
||||||
|
long analysisStart = PerformanceCounter.Companion.currentThreadCpuTime();
|
||||||
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(collector);
|
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(collector);
|
||||||
analyzerWithCompilerReport.analyzeAndReport(
|
analyzerWithCompilerReport.analyzeAndReport(
|
||||||
environment.getSourceFiles(), new Function0<AnalysisResult>() {
|
environment.getSourceFiles(), new Function0<AnalysisResult>() {
|
||||||
@@ -328,6 +317,10 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
long analysisNanos = PerformanceCounter.Companion.currentThreadCpuTime() - analysisStart;
|
||||||
|
String message = "Analyzed " + environment.getSourceFiles().size() + " files (" +
|
||||||
|
environment.getSourceLinesOfCode() + " lines) in " + TimeUnit.NANOSECONDS.toMillis(analysisNanos) + " ms";
|
||||||
|
K2JVMCompiler.reportPerf(environment.getConfiguration(), message);
|
||||||
|
|
||||||
AnalysisResult result = analyzerWithCompilerReport.getAnalysisResult();
|
AnalysisResult result = analyzerWithCompilerReport.getAnalysisResult();
|
||||||
assert result != null : "AnalysisResult should be non-null, compiling: " + environment.getSourceFiles();
|
assert result != null : "AnalysisResult should be non-null, compiling: " + environment.getSourceFiles();
|
||||||
@@ -381,7 +374,15 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
diagnosticHolder,
|
diagnosticHolder,
|
||||||
outputDirectory
|
outputDirectory
|
||||||
);
|
);
|
||||||
|
long generationStart = PerformanceCounter.Companion.currentThreadCpuTime();
|
||||||
|
|
||||||
KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION);
|
KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION);
|
||||||
|
|
||||||
|
long generationNanos = PerformanceCounter.Companion.currentThreadCpuTime() - generationStart;
|
||||||
|
String message = "Generated " + sourceFiles.size() + " files (" +
|
||||||
|
environment.countLinesOfCode(sourceFiles) + " lines) in " + TimeUnit.NANOSECONDS.toMillis(generationNanos) + " ms";
|
||||||
|
K2JVMCompiler.reportPerf(environment.getConfiguration(), message);
|
||||||
|
|
||||||
AnalyzerWithCompilerReport.reportDiagnostics(
|
AnalyzerWithCompilerReport.reportDiagnostics(
|
||||||
new FilteredJvmDiagnostics(
|
new FilteredJvmDiagnostics(
|
||||||
diagnosticHolder.getBindingContext().getDiagnostics(),
|
diagnosticHolder.getBindingContext().getDiagnostics(),
|
||||||
|
|||||||
+22
-20
@@ -19,12 +19,12 @@ package org.jetbrains.kotlin.load.kotlin
|
|||||||
import com.intellij.ide.highlighter.JavaClassFileType
|
import com.intellij.ide.highlighter.JavaClassFileType
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
import org.jetbrains.kotlin.utils.*
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||||
import java.io.IOException
|
import org.jetbrains.kotlin.utils.rethrow
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
public class VirtualFileKotlinClass private(
|
public class VirtualFileKotlinClass private(
|
||||||
public val file: VirtualFile,
|
public val file: VirtualFile,
|
||||||
@@ -51,28 +51,30 @@ public class VirtualFileKotlinClass private(
|
|||||||
|
|
||||||
companion object Factory {
|
companion object Factory {
|
||||||
private val LOG = Logger.getInstance(javaClass<VirtualFileKotlinClass>())
|
private val LOG = Logger.getInstance(javaClass<VirtualFileKotlinClass>())
|
||||||
|
private val perfCounter = PerformanceCounter("Binary class from Kotlin file")
|
||||||
|
|
||||||
deprecated("Use KotlinBinaryClassCache")
|
deprecated("Use KotlinBinaryClassCache")
|
||||||
fun create(file: VirtualFile): VirtualFileKotlinClass? {
|
fun create(file: VirtualFile): VirtualFileKotlinClass? {
|
||||||
assert(file.getFileType() == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
|
return perfCounter.time {
|
||||||
|
assert(file.getFileType() == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val byteContent = file.contentsToByteArray()
|
val byteContent = file.contentsToByteArray()
|
||||||
if (byteContent.isEmpty()) return null
|
if (!byteContent.isEmpty()) {
|
||||||
|
return@time FileBasedKotlinClass.create(byteContent) {
|
||||||
return FileBasedKotlinClass.create(byteContent) {
|
name, header, innerClasses ->
|
||||||
name, header, innerClasses ->
|
VirtualFileKotlinClass(file, name, header, innerClasses)
|
||||||
VirtualFileKotlinClass(file, name, header, innerClasses)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (e: FileNotFoundException) {
|
||||||
|
// Valid situation. User can delete jar file.
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
LOG.warn(renderFileReadingErrorMessage(file))
|
||||||
|
}
|
||||||
|
null
|
||||||
}
|
}
|
||||||
catch (e: FileNotFoundException) {
|
|
||||||
// Valid situation. User can delete jar file.
|
|
||||||
}
|
|
||||||
catch (e: Throwable) {
|
|
||||||
LOG.warn(renderFileReadingErrorMessage(file))
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderFileReadingErrorMessage(file: VirtualFile): String =
|
private fun renderFileReadingErrorMessage(file: VirtualFile): String =
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.resolve.calls;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function0;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
@@ -47,6 +49,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
|
|||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||||
|
import org.jetbrains.kotlin.util.PerformanceCounter;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -71,6 +74,9 @@ public class CallResolver {
|
|||||||
private TaskPrioritizer taskPrioritizer;
|
private TaskPrioritizer taskPrioritizer;
|
||||||
private AdditionalCheckerProvider additionalCheckerProvider;
|
private AdditionalCheckerProvider additionalCheckerProvider;
|
||||||
|
|
||||||
|
private static PerformanceCounter callResolvePerfCounter = new PerformanceCounter("Call resolve", true);
|
||||||
|
private static PerformanceCounter candidatePerfCounter = new PerformanceCounter("Call resolve candidate analysis", true);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
|
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
|
||||||
this.expressionTypingServices = expressionTypingServices;
|
this.expressionTypingServices = expressionTypingServices;
|
||||||
@@ -172,14 +178,19 @@ public class CallResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
|
||||||
@NotNull BasicCallResolutionContext context,
|
@NotNull final BasicCallResolutionContext context,
|
||||||
@NotNull Name name,
|
@NotNull final Name name,
|
||||||
@NotNull TracingStrategy tracing,
|
@NotNull final TracingStrategy tracing,
|
||||||
@NotNull CallableDescriptorCollectors<D> collectors,
|
@NotNull final CallableDescriptorCollectors<D> collectors,
|
||||||
@NotNull CallTransformer<D, F> callTransformer
|
@NotNull final CallTransformer<D, F> callTransformer
|
||||||
) {
|
) {
|
||||||
List<ResolutionTask<D, F>> tasks = taskPrioritizer.<D, F>computePrioritizedTasks(context, name, tracing, collectors);
|
return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
|
||||||
return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
|
@Override
|
||||||
|
public OverloadResolutionResults<F> invoke() {
|
||||||
|
List<ResolutionTask<D, F>> tasks = taskPrioritizer.<D, F>computePrioritizedTasks(context, name, tracing, collectors);
|
||||||
|
return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -195,14 +206,19 @@ public class CallResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
|
||||||
@NotNull BasicCallResolutionContext context,
|
@NotNull final BasicCallResolutionContext context,
|
||||||
@NotNull Collection<ResolutionCandidate<D>> candidates,
|
@NotNull final Collection<ResolutionCandidate<D>> candidates,
|
||||||
@NotNull CallTransformer<D, F> callTransformer,
|
@NotNull final CallTransformer<D, F> callTransformer,
|
||||||
@NotNull TracingStrategy tracing
|
@NotNull final TracingStrategy tracing
|
||||||
) {
|
) {
|
||||||
List<ResolutionTask<D, F>> prioritizedTasks =
|
return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
|
||||||
taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
|
@Override
|
||||||
return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
|
public OverloadResolutionResults<F> invoke() {
|
||||||
|
List<ResolutionTask<D, F>> prioritizedTasks =
|
||||||
|
taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
|
||||||
|
return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -388,19 +404,24 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
|
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
|
||||||
@NotNull Call call,
|
@NotNull final Call call,
|
||||||
@NotNull TracingStrategy tracing,
|
@NotNull final TracingStrategy tracing,
|
||||||
@NotNull ResolutionContext<?> context,
|
@NotNull final ResolutionContext<?> context,
|
||||||
@NotNull ResolutionCandidate<CallableDescriptor> candidate,
|
@NotNull final ResolutionCandidate<CallableDescriptor> candidate,
|
||||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
|
@Nullable final MutableDataFlowInfoForArguments dataFlowInfoForArguments
|
||||||
) {
|
) {
|
||||||
BasicCallResolutionContext basicCallResolutionContext =
|
return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<FunctionDescriptor>>() {
|
||||||
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
@Override
|
||||||
|
public OverloadResolutionResults<FunctionDescriptor> invoke() {
|
||||||
|
BasicCallResolutionContext basicCallResolutionContext =
|
||||||
|
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
||||||
|
|
||||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
||||||
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
||||||
basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
||||||
return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
|
||||||
@@ -547,31 +568,37 @@ public class CallResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
|
||||||
@NotNull ResolutionTask<D, F> task,
|
@NotNull final ResolutionTask<D, F> task,
|
||||||
@NotNull CallTransformer<D, F> callTransformer
|
@NotNull final CallTransformer<D, F> callTransformer
|
||||||
) {
|
) {
|
||||||
|
|
||||||
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
|
for (final ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
|
||||||
TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
|
candidatePerfCounter.time(new Function0<Unit>() {
|
||||||
task.trace, "trace to resolve candidate");
|
@Override
|
||||||
Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
|
public Unit invoke() {
|
||||||
for (CallCandidateResolutionContext<D> context : contexts) {
|
TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
|
||||||
|
task.trace, "trace to resolve candidate");
|
||||||
|
Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
|
||||||
|
for (CallCandidateResolutionContext<D> context : contexts) {
|
||||||
|
|
||||||
candidateResolver.performResolutionForCandidateCall(context, task);
|
candidateResolver.performResolutionForCandidateCall(context, task);
|
||||||
|
|
||||||
/* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
|
/* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
|
||||||
to have a binding to variable while 'invoke' call resolve */
|
to have a binding to variable while 'invoke' call resolve */
|
||||||
task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
|
task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
|
||||||
|
|
||||||
Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, this, task);
|
Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, CallResolver.this, task);
|
||||||
|
|
||||||
for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
|
for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
|
||||||
BindingTrace trace = resolvedCall.getTrace();
|
BindingTrace trace = resolvedCall.getTrace();
|
||||||
task.tracing.bindReference(trace, resolvedCall);
|
task.tracing.bindReference(trace, resolvedCall);
|
||||||
task.tracing.bindResolvedCall(trace, resolvedCall);
|
task.tracing.bindResolvedCall(trace, resolvedCall);
|
||||||
task.addResolvedCall(resolvedCall);
|
task.addResolvedCall(resolvedCall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Unit.INSTANCE$;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
|
OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.util
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
public class PerformanceCounter jvmOverloads constructor (val name: String, val reenterable: Boolean = false) {
|
||||||
|
companion object {
|
||||||
|
private val threadMxBean = ManagementFactory.getThreadMXBean()
|
||||||
|
private val allCounters = arrayListOf<PerformanceCounter>()
|
||||||
|
|
||||||
|
private val enteredCounters = ThreadLocal<MutableSet<PerformanceCounter>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
threadMxBean.setThreadCpuTimeEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enterCounter(counter: PerformanceCounter): Boolean {
|
||||||
|
var enteredCountersInThread = enteredCounters.get()
|
||||||
|
if (enteredCountersInThread == null) {
|
||||||
|
enteredCountersInThread = hashSetOf(counter)
|
||||||
|
enteredCounters.set(enteredCountersInThread)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return enteredCountersInThread.add(counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun leaveCounter(counter: PerformanceCounter) {
|
||||||
|
enteredCounters.get()?.remove(counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun currentThreadCpuTime(): Long = threadMxBean.getCurrentThreadUserTime()
|
||||||
|
|
||||||
|
public fun report(consumer: (String) -> Unit) {
|
||||||
|
allCounters.forEach { it.report(consumer) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var count: Int = 0
|
||||||
|
private var totalTimeNanos: Long = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
allCounters.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun increment() {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun time<T>(block: () -> T): T {
|
||||||
|
count++
|
||||||
|
val needTime = !reenterable || enterCounter(this)
|
||||||
|
val startTime = currentThreadCpuTime()
|
||||||
|
try {
|
||||||
|
return block()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (needTime) {
|
||||||
|
totalTimeNanos += currentThreadCpuTime() - startTime
|
||||||
|
if (reenterable) leaveCounter(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun report(consumer: (String) -> Unit) {
|
||||||
|
if (totalTimeNanos == 0L) {
|
||||||
|
consumer("$name performed $count times")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val millis = TimeUnit.NANOSECONDS.toMillis(totalTimeNanos)
|
||||||
|
consumer("$name performed $count times, total time $millis ms")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,7 +73,11 @@ public class CliBaseTest {
|
|||||||
.replace("expected ABI version is " + Integer.toString(JvmAbi.VERSION), "expected ABI version is $ABI_VERSION$")
|
.replace("expected ABI version is " + Integer.toString(JvmAbi.VERSION), "expected ABI version is $ABI_VERSION$")
|
||||||
.replace("\\", "/");
|
.replace("\\", "/");
|
||||||
|
|
||||||
return normalizedOutputWithoutExitCode + exitCode;
|
return removePerfOutput(normalizedOutputWithoutExitCode) + exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String removePerfOutput(String output) {
|
||||||
|
return output.replaceAll("INFO: PERF:.+\n", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeCompilerCompareOutput(@NotNull CLICompiler<?> compiler, @NotNull String testDataDir) throws Exception {
|
private void executeCompilerCompareOutput(@NotNull CLICompiler<?> compiler, @NotNull String testDataDir) throws Exception {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.integration;
|
|||||||
|
|
||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.cli.CliBaseTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -38,7 +39,8 @@ public abstract class AntTaskBaseTest extends KotlinIntegrationTestBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String normalizeOutput(String content) {
|
protected String normalizeOutput(String content) {
|
||||||
return super.normalizeOutput(content).replaceAll("Total time: .+\n", "Total time: [time]\n");
|
return CliBaseTest.removePerfOutput(super.normalizeOutput(content))
|
||||||
|
.replaceAll("Total time: .+\n", "Total time: [time]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int runAnt(String logName, String scriptName, String... extraArgs) throws Exception {
|
private int runAnt(String logName, String scriptName, String... extraArgs) throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user