From 96422ea3fe750ca19a68e148fb1f34a4fc30cb32 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 21 Sep 2020 16:49:26 +0300 Subject: [PATCH] FIR IDE: introduce highlighting performance test --- build.gradle.kts | 7 + generators/build.gradle.kts | 1 + .../kotlin/generators/tests/GenerateTests.kt | 6 + .../build.gradle.kts | 93 +++++++ .../AbstractFirHighlightingPerformanceTest.kt | 110 ++++++++ ...rHighlightingPerformanceTestGenerated.java | 253 ++++++++++++++++++ prepare/idea-plugin/build.gradle.kts | 1 + settings.gradle | 2 + 8 files changed, 473 insertions(+) create mode 100644 idea/idea-fir-performance-tests/build.gradle.kts create mode 100644 idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/AbstractFirHighlightingPerformanceTest.kt create mode 100644 idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingPerformanceTestGenerated.java diff --git a/build.gradle.kts b/build.gradle.kts index 06905754fef..160dc6a5ba8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -786,6 +786,13 @@ tasks { ) } + register("idea-fir-plugin-performance-tests") { + dependsOn("dist") + dependsOn( + ":idea:idea-fir-performance-tests:ideaFirPerformanceTest" + ) + } + register("android-ide-tests") { dependsOn("dist") dependsOn( diff --git a/generators/build.gradle.kts b/generators/build.gradle.kts index c8f805630db..24af3bdc15c 100644 --- a/generators/build.gradle.kts +++ b/generators/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { testCompile(projectTests(":compiler:cli")) testCompile(projectTests(":idea:idea-maven")) testCompile(projectTests(":idea:idea-fir")) + testCompile(projectTests(":idea:idea-fir-performance-tests")) testCompile(projectTests(":idea:idea-frontend-fir")) testCompile(projectTests(":idea:idea-frontend-fir:idea-fir-low-level-api")) testCompile(projectTests(":j2k")) diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 7d78fea0411..d5349e24b06 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -1044,6 +1044,12 @@ fun main(args: Array) { } } + testGroup("idea/idea-fir-performance-tests/tests", "idea") { + testClass { + model("testData/highlighter") + } + } + testGroup("idea/idea-fir/tests", "idea/testData") { testClass { model("resolve/references", pattern = KT_WITHOUT_DOTS_IN_NAME) diff --git a/idea/idea-fir-performance-tests/build.gradle.kts b/idea/idea-fir-performance-tests/build.gradle.kts new file mode 100644 index 00000000000..40386845a4d --- /dev/null +++ b/idea/idea-fir-performance-tests/build.gradle.kts @@ -0,0 +1,93 @@ +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + compile(project(":idea:idea-frontend-fir")) + compile(project(":idea:formatter")) + compile(intellijDep()) + compile(intellijCoreDep()) + +// + compile(project(":idea:idea-core")) + compile(project(":idea")) +// + testCompile(projectTests(":idea:performanceTests")) + + + testCompile(toolsJar()) + testCompile(projectTests(":idea")) + testCompile(projectTests(":idea:idea-fir")) + compile(project(":idea:idea-fir")) + testCompile(projectTests(":compiler:tests-common")) + testCompile(projectTests(":idea:idea-test-framework")) + testCompile(projectTests(":idea:idea-frontend-fir")) + testCompile(project(":kotlin-test:kotlin-test-junit")) + testCompile(commonDep("junit:junit")) + + testCompileOnly(intellijDep()) + testRuntime(intellijDep()) + + Platform[192].orHigher { + compile(intellijPluginDep("java")) + } +} + +sourceSets { + "main" { projectDefault() } + "test" { projectDefault() } +} + +if (rootProject.findProperty("idea.fir.plugin") == "true") { + projectTest(parallel = true) { + dependsOn(":dist") + workingDir = rootDir + } +} + +testsJar() + +projectTest(taskName = "ideaFirPerformanceTest") { + val currentOs = org.gradle.internal.os.OperatingSystem.current() + + if (!currentOs.isWindows) { + System.getenv("ASYNC_PROFILER_HOME")?.let { asyncProfilerHome -> + classpath += files("$asyncProfilerHome/build/async-profiler.jar") + } + } + + workingDir = rootDir + + jvmArgs?.removeAll { it.startsWith("-Xmx") } + + maxHeapSize = "3g" + jvmArgs("-Didea.debug.mode=true") + jvmArgs("-XX:SoftRefLRUPolicyMSPerMB=50") + + jvmArgs( + "-XX:+UseCompressedOops", + "-Didea.ProcessCanceledException=disabled", + "-XX:+UseConcMarkSweepGC" + ) + + System.getenv("YOURKIT_PROFILER_HOME")?.let {yourKitHome -> + when { + currentOs.isLinux -> { + jvmArgs("-agentpath:$yourKitHome/bin/linux-x86-64/libyjpagent.so") + classpath += files("$yourKitHome/lib/yjp-controller-api-redist.jar") + } + currentOs.isMacOsX -> { + jvmArgs("-agentpath:$yourKitHome/Contents/Resources/bin/mac/libyjpagent.dylib=delay=5000,_socket_timeout_ms=120000,disablealloc,disable_async_sampling,disablenatives") + classpath += files("$yourKitHome/Contents/Resources/lib/yjp-controller-api-redist.jar") + } + } + } + + doFirst { + systemProperty("idea.home.path", intellijRootDir().canonicalPath) + project.findProperty("cacheRedirectorEnabled")?.let { + systemProperty("kotlin.test.gradle.import.arguments", "-PcacheRedirectorEnabled=$it") + } + } +} \ No newline at end of file diff --git a/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/AbstractFirHighlightingPerformanceTest.kt b/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/AbstractFirHighlightingPerformanceTest.kt new file mode 100644 index 00000000000..864d857a49a --- /dev/null +++ b/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/AbstractFirHighlightingPerformanceTest.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.highlighter + +import com.intellij.codeInsight.daemon.impl.HighlightInfo +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiDocumentManager +import com.intellij.testFramework.EdtTestUtil +import com.intellij.testFramework.ExpectedHighlightingData +import com.intellij.testFramework.RunAll +import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl +import com.intellij.util.ThrowableRunnable +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.perf.Stats +import org.jetbrains.kotlin.idea.perf.TestData +import org.jetbrains.kotlin.idea.perf.performanceTest +import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import java.io.File + +abstract class AbstractFirHighlightingPerformanceTest : AbstractHighlightingTest() { + companion object { + @JvmStatic + var warmedUp: Boolean = false + + @JvmStatic + val stats: Stats = Stats("fir-highlight") + + } + + override fun isFirPlugin() = true + + override fun setUp() { + super.setUp() + + if (!warmedUp) { + doWarmUpPerfTest() + warmedUp = true + } + } + + override fun tearDown() { + commitAllDocuments() + RunAll( + ThrowableRunnable { super.tearDown() }, + ThrowableRunnable { stats.flush() } + ).run() + } + + private fun doWarmUpPerfTest() { + innerPerfTest(Stats.WARM_UP) { + myFixture.configureByText( + KotlinFileType.INSTANCE, + "class Foo {\n private val value: String? = null\n}" + ) + } + } + + override fun doTest(filePath: String) { + val testName = getTestName(false) + val ignore = InTextDirectivesUtils.isDirectiveDefined(FileUtil.loadFile(File(filePath)), "IGNORE_FIR") + if (ignore) return + innerPerfTest(testName) { + myFixture.configureByFile(fileName()) + commitAllDocuments() + removeInfoMarkers() + + val file = myFixture.file + val offset = file.textOffset + assertTrue("side effect: to load the text", offset >= 0) + + // to load AST for changed files before it's prohibited by "fileTreeAccessFilter" + CodeInsightTestFixtureImpl.ensureIndexesUpToDate(project) + } + } + + private fun removeInfoMarkers() { + ExpectedHighlightingData(editor.document, true, true).init() + + EdtTestUtil.runInEdtAndWait { + PsiDocumentManager.getInstance(project).commitAllDocuments() + } + } + + private fun innerPerfTest(name: String, setUpBody: (TestData>) -> Unit) { + performanceTest> { + name(name) + stats(stats) + setUp { + setUpBody(it) + } + test { + it.value = perfTestCore() + } + tearDown { + assertNotNull("no reasons to validate output as it is a performance test", it.value) + runWriteAction { + myFixture.file.delete() + } + } + } + } + + private fun perfTestCore(): MutableList = myFixture.doHighlighting() + +} \ No newline at end of file diff --git a/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingPerformanceTestGenerated.java b/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingPerformanceTestGenerated.java new file mode 100644 index 00000000000..78c7287d106 --- /dev/null +++ b/idea/idea-fir-performance-tests/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingPerformanceTestGenerated.java @@ -0,0 +1,253 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.highlighter; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/highlighter") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class FirHighlightingPerformanceTestGenerated extends AbstractFirHighlightingPerformanceTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInHighlighter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/highlighter"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("Annotations.kt") + public void testAnnotations() throws Exception { + runTest("idea/testData/highlighter/Annotations.kt"); + } + + @TestMetadata("AutoCreatedItParameter.kt") + public void testAutoCreatedItParameter() throws Exception { + runTest("idea/testData/highlighter/AutoCreatedItParameter.kt"); + } + + @TestMetadata("Destructuring.kt") + public void testDestructuring() throws Exception { + runTest("idea/testData/highlighter/Destructuring.kt"); + } + + @TestMetadata("Dynamic.kt") + public void testDynamic() throws Exception { + runTest("idea/testData/highlighter/Dynamic.kt"); + } + + @TestMetadata("Enums.kt") + public void testEnums() throws Exception { + runTest("idea/testData/highlighter/Enums.kt"); + } + + @TestMetadata("Field.kt") + public void testField() throws Exception { + runTest("idea/testData/highlighter/Field.kt"); + } + + @TestMetadata("Functions.kt") + public void testFunctions() throws Exception { + runTest("idea/testData/highlighter/Functions.kt"); + } + + @TestMetadata("InvokeCall.kt") + public void testInvokeCall() throws Exception { + runTest("idea/testData/highlighter/InvokeCall.kt"); + } + + @TestMetadata("JavaTypes.kt") + public void testJavaTypes() throws Exception { + runTest("idea/testData/highlighter/JavaTypes.kt"); + } + + @TestMetadata("KDoc.kt") + public void testKDoc() throws Exception { + runTest("idea/testData/highlighter/KDoc.kt"); + } + + @TestMetadata("KotlinInjection.kt") + public void testKotlinInjection() throws Exception { + runTest("idea/testData/highlighter/KotlinInjection.kt"); + } + + @TestMetadata("Labels.kt") + public void testLabels() throws Exception { + runTest("idea/testData/highlighter/Labels.kt"); + } + + @TestMetadata("NamedArguments.kt") + public void testNamedArguments() throws Exception { + runTest("idea/testData/highlighter/NamedArguments.kt"); + } + + @TestMetadata("NonNullAssertion.kt") + public void testNonNullAssertion() throws Exception { + runTest("idea/testData/highlighter/NonNullAssertion.kt"); + } + + @TestMetadata("Object.kt") + public void testObject() throws Exception { + runTest("idea/testData/highlighter/Object.kt"); + } + + @TestMetadata("PropertiesWithPropertyDeclarations.kt") + public void testPropertiesWithPropertyDeclarations() throws Exception { + runTest("idea/testData/highlighter/PropertiesWithPropertyDeclarations.kt"); + } + + @TestMetadata("SmartCast.kt") + public void testSmartCast() throws Exception { + runTest("idea/testData/highlighter/SmartCast.kt"); + } + + @TestMetadata("Suspend.kt") + public void testSuspend() throws Exception { + runTest("idea/testData/highlighter/Suspend.kt"); + } + + @TestMetadata("SyntheticExtensionProperty.kt") + public void testSyntheticExtensionProperty() throws Exception { + runTest("idea/testData/highlighter/SyntheticExtensionProperty.kt"); + } + + @TestMetadata("Todo.kt") + public void testTodo() throws Exception { + runTest("idea/testData/highlighter/Todo.kt"); + } + + @TestMetadata("TopLevelDestructuring.kt") + public void testTopLevelDestructuring() throws Exception { + runTest("idea/testData/highlighter/TopLevelDestructuring.kt"); + } + + @TestMetadata("TopLevelOpenSuspendFun.kt") + public void testTopLevelOpenSuspendFun() throws Exception { + runTest("idea/testData/highlighter/TopLevelOpenSuspendFun.kt"); + } + + @TestMetadata("TypeAlias.kt") + public void testTypeAlias() throws Exception { + runTest("idea/testData/highlighter/TypeAlias.kt"); + } + + @TestMetadata("TypesAndAnnotations.kt") + public void testTypesAndAnnotations() throws Exception { + runTest("idea/testData/highlighter/TypesAndAnnotations.kt"); + } + + @TestMetadata("Variables.kt") + public void testVariables() throws Exception { + runTest("idea/testData/highlighter/Variables.kt"); + } + + @TestMetadata("VariablesAsFunctions.kt") + public void testVariablesAsFunctions() throws Exception { + runTest("idea/testData/highlighter/VariablesAsFunctions.kt"); + } + + @TestMetadata("idea/testData/highlighter/deprecated") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Deprecated extends AbstractFirHighlightingPerformanceTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInDeprecated() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/highlighter/deprecated"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("Class.kt") + public void testClass() throws Exception { + runTest("idea/testData/highlighter/deprecated/Class.kt"); + } + + @TestMetadata("ClassObject.kt") + public void testClassObject() throws Exception { + runTest("idea/testData/highlighter/deprecated/ClassObject.kt"); + } + + @TestMetadata("Constructor.kt") + public void testConstructor() throws Exception { + runTest("idea/testData/highlighter/deprecated/Constructor.kt"); + } + + @TestMetadata("ExtensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("idea/testData/highlighter/deprecated/ExtensionFunction.kt"); + } + + @TestMetadata("Function.kt") + public void testFunction() throws Exception { + runTest("idea/testData/highlighter/deprecated/Function.kt"); + } + + @TestMetadata("Get.kt") + public void testGet() throws Exception { + runTest("idea/testData/highlighter/deprecated/Get.kt"); + } + + @TestMetadata("Getter.kt") + public void testGetter() throws Exception { + runTest("idea/testData/highlighter/deprecated/Getter.kt"); + } + + @TestMetadata("Inc.kt") + public void testInc() throws Exception { + runTest("idea/testData/highlighter/deprecated/Inc.kt"); + } + + @TestMetadata("Invalid.kt") + public void testInvalid() throws Exception { + runTest("idea/testData/highlighter/deprecated/Invalid.kt"); + } + + @TestMetadata("Invoke.kt") + public void testInvoke() throws Exception { + runTest("idea/testData/highlighter/deprecated/Invoke.kt"); + } + + @TestMetadata("Operation.kt") + public void testOperation() throws Exception { + runTest("idea/testData/highlighter/deprecated/Operation.kt"); + } + + @TestMetadata("Property.kt") + public void testProperty() throws Exception { + runTest("idea/testData/highlighter/deprecated/Property.kt"); + } + + @TestMetadata("RangeTo.kt") + public void testRangeTo() throws Exception { + runTest("idea/testData/highlighter/deprecated/RangeTo.kt"); + } + + @TestMetadata("Setter.kt") + public void testSetter() throws Exception { + runTest("idea/testData/highlighter/deprecated/Setter.kt"); + } + + @TestMetadata("SuperCall.kt") + public void testSuperCall() throws Exception { + runTest("idea/testData/highlighter/deprecated/SuperCall.kt"); + } + + @TestMetadata("Trait.kt") + public void testTrait() throws Exception { + runTest("idea/testData/highlighter/deprecated/Trait.kt"); + } + } +} diff --git a/prepare/idea-plugin/build.gradle.kts b/prepare/idea-plugin/build.gradle.kts index 35ca0ed37b6..d8019085626 100644 --- a/prepare/idea-plugin/build.gradle.kts +++ b/prepare/idea-plugin/build.gradle.kts @@ -107,6 +107,7 @@ val projectsToShadow by extra(listOf( ":idea:idea-frontend-fir", ":idea:idea-frontend-api", ":idea:idea-frontend-fir:idea-fir-low-level-api", + ":idea:idea-frontend-fir:idea-fir-performance-tests", ":idea:idea-fir", *if (Ide.IJ()) arrayOf( diff --git a/settings.gradle b/settings.gradle index 44addd8f4ef..87c7f875f4a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -160,6 +160,7 @@ include ":benchmarks", ":idea:ide-common", ":idea:idea-core", ":idea:idea-fir", + ":idea:idea-fir-performance-tests", ":idea:kotlin-gradle-tooling", ":idea:line-indent-provider", ":idea:idea-android", @@ -323,6 +324,7 @@ include ":compiler:fir:cones", ":compiler:fir:analysis-tests" include ":idea:idea-frontend-fir:idea-fir-low-level-api" +include ":idea:idea-frontend-fir:idea-fir-performance-tests" include ":plugins:parcelize:parcelize-compiler", ":plugins:parcelize:parcelize-ide",