diff --git a/compiler/fir/lightTree/build.gradle.kts b/compiler/fir/lightTree/build.gradle.kts index ba0cf79460a..f985d0d6b59 100644 --- a/compiler/fir/lightTree/build.gradle.kts +++ b/compiler/fir/lightTree/build.gradle.kts @@ -4,6 +4,7 @@ plugins { } group = "org.jetbrains.kotlin.fir" +val jmhVersion = "1.21" repositories { mavenCentral() @@ -20,6 +21,10 @@ dependencies { compile("junit", "junit", "4.4") compile(projectTests(":compiler:fir:psi2fir")) + + compile("org.openjdk.jmh", "jmh-core", jmhVersion) + compile("org.openjdk.jmh", "jmh-generator-bytecode", jmhVersion) + compile("org.openjdk.jmh", "jmh-generator-annprocess", jmhVersion) } sourceSets { @@ -30,3 +35,60 @@ sourceSets { projectTest { workingDir = rootDir } + +val compactClasspath by tasks.creating(Jar::class) { + archiveAppendix.set("classpath") + inputs.files(sourceSets["main"].runtimeClasspath + sourceSets["test"].runtimeClasspath) + doFirst { + manifest { + attributes["Class-Path"] = (sourceSets["main"].runtimeClasspath + sourceSets["test"].runtimeClasspath).files + .joinToString(separator = " ", transform = { it.toURI().toURL().toString() }) + } + } +} + +val jmhBytecode by tasks.creating(JavaExec::class) { + tasks["classes"].mustRunAfter(tasks["clean"]) + tasks["compactClasspath"].mustRunAfter(tasks["classes"]) + dependsOn(tasks["clean"]) + dependsOn(tasks["classes"]) + dependsOn(tasks["compactClasspath"]) + + classpath = files(tasks["compactClasspath"].outputs.files.singleFile.absolutePath) + main = "org.openjdk.jmh.generators.bytecode.JmhBytecodeGenerator" + args( + "${project.buildDir}/classes/kotlin/test", "${project.buildDir}/generated-sources/jmh/", + "${project.buildDir}/classes/kotlin/test", "default" + ) +} + +tasks { + compileTestJava { + source(fileTree("${project.buildDir}/generated-sources/jmh/")) + destinationDir = file("${project.buildDir}/generated-classes/jmh/") + } +} + +val jmhCompile by tasks.creating(JavaCompile::class) { + /*classpath = sourceSets["test"].runtimeClasspath + files("${project.buildDir}/generated-sources/jmh/") + + source(fileTree("${project.buildDir}/generated-sources/jmh/")) + destinationDir = file("${project.buildDir}/generated-classes/jmh/")*/ +} + +val jmhExec by tasks.creating(JavaExec::class) { + dependsOn(tasks["compileTestJava"]) + doFirst { + classpath = files( + tasks["compactClasspath"].outputs.files.singleFile.absolutePath, + "${project.buildDir}/generated-classes/jmh/", + "${project.buildDir}/classes/kotlin/test" + ) + } + + main = "org.openjdk.jmh.Main" + + workingDir = rootDir + systemProperty("idea.home.path", project.intellij.localPath) + configurations.plusAssign(project.configurations["compile"]) +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/TotalKotlinTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt similarity index 97% rename from compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/TotalKotlinTest.kt rename to compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt index 6f9b9f4a53c..fefd0b54a9f 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/TotalKotlinTest.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt @@ -3,7 +3,7 @@ * that can be found in the license/LICENSE.txt file. */ -package org.jetbrains.kotlin.fir.lightTree.totalKotlin +package org.jetbrains.kotlin.fir.lightTree import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.CharsetToolkit @@ -12,7 +12,6 @@ import com.intellij.testFramework.TestDataPath import com.intellij.util.PathUtil import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase -import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.JUnit3RunnerWithInners diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/AbstractBenchmark.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/AbstractBenchmark.kt new file mode 100644 index 00000000000..45efe44c56d --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/AbstractBenchmark.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.benchmark + +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.CharsetToolkit +import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase +import org.openjdk.jmh.annotations.* +import java.io.File + +@BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5, batchSize = 1) +@Measurement(iterations = 5, batchSize = 1) +@Fork(1) +open class AbstractBenchmark { + private val files = mutableMapOf>() + + protected fun readFiles(ignoreTestData: Boolean, path: String) { + val root = File(path) + + println("BASE PATH: $path") + for (file in root.walkTopDown()) { + if (file.isDirectory) continue + if (ignoreTestData && (file.path.contains("testData") || file.path.contains("resources"))) continue + if (file.extension != "kt") continue + + val text = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim() + files[file.name] = Pair(file, text) + } + } + + //TODO null check + protected fun getFileByName(fileName: String): Pair { + return files[fileName]!! + } + + protected fun forEachFile(f: (String, File) -> Unit) { + for ((file, text) in files.values) { + f(text, file) + } + } +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/LightTree2FirGenerator.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/LightTree2FirGenerator.kt new file mode 100644 index 00000000000..aad7a2387ed --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/LightTree2FirGenerator.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.benchmark + +import com.intellij.psi.impl.DebugUtil +import org.jetbrains.kotlin.fir.FirRenderer +import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase +import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir +import org.jetbrains.kotlin.parsing.KotlinParserDefinition +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import java.io.File + +@State(Scope.Benchmark) +open class LightTree2FirGenerator : TreeGenerator, AbstractRawFirBuilderTestCase() { + private var lightTreeConverter: LightTree2Fir? = null + + override fun generateBaseTree(text: String, file: File) { + val lightTree = lightTreeConverter!!.buildLightTree(text) + DebugUtil.lightTreeToString(lightTree, false) + } + + override fun generateFir(text: String, file: File) { + val firFile = lightTreeConverter!!.buildFirFile(text, file.name) + StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString() + } + + private fun createConverter() { + val parserDefinition = KotlinParserDefinition() + val lexer = parserDefinition.createLexer(project) + lightTreeConverter = LightTree2Fir(true, parserDefinition, lexer) + } + + override fun setUp() { + super.setUp() + createConverter() + } + + override fun tearDown() { + super.tearDown() + } +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/Psi2FirGenerator.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/Psi2FirGenerator.kt new file mode 100644 index 00000000000..878d954edb0 --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/Psi2FirGenerator.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.benchmark + +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.impl.DebugUtil +import com.intellij.util.PathUtil +import org.jetbrains.kotlin.fir.FirRenderer +import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase +import org.jetbrains.kotlin.psi.KtFile +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import java.io.File + +@State(Scope.Benchmark) +open class Psi2FirGenerator : TreeGenerator, AbstractRawFirBuilderTestCase() { + override fun generateBaseTree(text: String, file: File) { + val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile + DebugUtil.psiTreeToString(ktFile, false) + } + + override fun generateFir(text: String, file: File) { + val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile + val firFile = ktFile.toFirFile(stubMode = true) + StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString() + } + + override fun setUp() { + super.setUp() + } + + override fun tearDown() { + super.tearDown() + } +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/TreeGenerator.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/TreeGenerator.kt new file mode 100644 index 00000000000..5e8e794cf59 --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/TreeGenerator.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.benchmark + +import java.io.File + +interface TreeGenerator { + fun generateBaseTree(text: String, file: File) + fun generateFir(text: String, file: File) + fun setUp() + fun tearDown() +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/totalKotlin/AbstractTotalKotlinBenchmark.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/totalKotlin/AbstractTotalKotlinBenchmark.kt new file mode 100644 index 00000000000..d74338ec101 --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/totalKotlin/AbstractTotalKotlinBenchmark.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.benchmark.totalKotlin + +import org.jetbrains.kotlin.fir.lightTree.benchmark.* +import org.openjdk.jmh.annotations.* + +@State(Scope.Benchmark) +abstract class AbstractTotalKotlinBenchmark : AbstractBenchmark() { + abstract val generator: TreeGenerator + + @Setup + fun setUp() { + generator.setUp() + readFiles(true, System.getProperty("user.dir")) + } + + @TearDown + fun tearDown() { + generator.tearDown() + } + + @Benchmark + fun testTotalKotlinOnlyBaseTree() { + forEachFile { text, file -> generator.generateBaseTree(text, file) } + } + + @Benchmark + fun testTotalKotlinFir() { + forEachFile { text, file -> generator.generateFir(text, file) } + } +} + +open class LightTree2FirTotalKotlinBenchmark(override val generator: TreeGenerator = LightTree2FirGenerator()) : + AbstractTotalKotlinBenchmark() + +open class Psi2FirTotalKotlinBenchmark(override val generator: TreeGenerator = Psi2FirGenerator()) : + AbstractTotalKotlinBenchmark() \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/AbstractTotalKotlinTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/AbstractTotalKotlinTest.kt deleted file mode 100644 index 0d573336070..00000000000 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/AbstractTotalKotlinTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.totalKotlin - -import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.vfs.CharsetToolkit -import com.intellij.testFramework.TestDataPath -import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners -import org.junit.runner.RunWith -import java.io.File -import kotlin.system.measureNanoTime - -@TestDataPath("/") -@RunWith(JUnit3RunnerWithInners::class) -abstract class AbstractTotalKotlinTest(private val treeName: String) : AbstractRawFirBuilderTestCase() { - protected abstract fun generateTree(onlyBaseTree: Boolean, text: String, file: File) - - fun totalKotlinTest(onlyBaseTree: Boolean) { - val path = System.getProperty("user.dir") - val root = File(path) - var counter = 0 - var time = 0L - - if (onlyBaseTree) println("$treeName generation") else println("Fir from $treeName converter") - println("BASE PATH: $path") - for (file in root.walkTopDown()) { - if (file.isDirectory) continue - if (file.path.contains("testData") || file.path.contains("resources")) continue - if (file.extension != "kt") continue - - val text = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim() - time += measureNanoTime { - generateTree(onlyBaseTree, text, file) - } - - counter++ - } - println("SUCCESS!") - println("TIME PER FILE: ${(time / counter) * 1e-6} ms, COUNTER: $counter") - } -} - diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/LightTree2FirConverterTotalTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/LightTree2FirConverterTotalTest.kt deleted file mode 100644 index 08b4b4fb7cb..00000000000 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/LightTree2FirConverterTotalTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.totalKotlin - -import com.intellij.psi.impl.DebugUtil -import com.intellij.testFramework.TestDataPath -import org.jetbrains.kotlin.fir.FirRenderer -import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase -import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir -import org.jetbrains.kotlin.parsing.KotlinParserDefinition -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners -import org.junit.runner.RunWith -import java.io.File - -@TestDataPath("/") -@RunWith(JUnit3RunnerWithInners::class) -class LightTree2FirConverterTotalTest : AbstractTotalKotlinTest("LightTree") { - private var lightTreeConverter: LightTree2Fir? = null - - override fun generateTree(onlyBaseTree: Boolean, text: String, file: File) { - if (onlyBaseTree) { - val lightTree = lightTreeConverter!!.buildLightTree(text) - DebugUtil.lightTreeToString(lightTree, false) - } else { - val firFile = lightTreeConverter!!.buildFirFile(text, file.name) - StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString() - } - } - - private fun createConverter() { - val parserDefinition = KotlinParserDefinition() - val lexer = parserDefinition.createLexer(myProject) - lightTreeConverter = LightTree2Fir(true, parserDefinition, lexer) - } - - fun testTotalKotlinOnlyLightTree() { - createConverter() - totalKotlinTest(true) - } - - fun testTotalKotlinFirFromLightTree() { - createConverter() - totalKotlinTest(false) - } -} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/Psi2FirConverterTotalTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/Psi2FirConverterTotalTest.kt deleted file mode 100644 index e87d0a7d271..00000000000 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/totalKotlin/Psi2FirConverterTotalTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. 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.fir.lightTree.totalKotlin - -import com.intellij.openapi.util.io.FileUtil -import com.intellij.psi.impl.DebugUtil -import com.intellij.testFramework.TestDataPath -import com.intellij.util.PathUtil -import org.jetbrains.kotlin.fir.FirRenderer -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners -import org.junit.runner.RunWith -import java.io.File - -@TestDataPath("/") -@RunWith(JUnit3RunnerWithInners::class) -class Psi2FirConverterTotalTest : AbstractTotalKotlinTest("Psi") { - override fun generateTree(onlyBaseTree: Boolean, text: String, file: File) { - val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile - if (onlyBaseTree) { - DebugUtil.psiTreeToString(ktFile, false) - } else { - val firFile = ktFile.toFirFile(stubMode = true) - StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString() - } - } - - fun testTotalKotlinOnlyPsi() { - totalKotlinTest(true) - } - - fun testTotalKotlinFirFromPsi() { - totalKotlinTest(false) - } -} \ No newline at end of file