Create benchmark for light tree FIR builder (including coroutines test)

This commit is contained in:
Ivan Cilcic
2019-06-03 13:41:07 +03:00
committed by Mikhail Glukhikh
parent 0a8d0baa59
commit f07d85eb83
13 changed files with 153 additions and 62 deletions
+1
View File
@@ -0,0 +1 @@
testData
+20 -1
View File
@@ -1,10 +1,16 @@
import org.ajoberstar.grgit.Grgit
plugins { plugins {
kotlin("jvm") kotlin("jvm")
id("org.jetbrains.intellij") version "0.4.5" id("org.jetbrains.intellij") version "0.4.5"
//git plugin
id("org.ajoberstar.grgit") version "3.1.1"
} }
group = "org.jetbrains.kotlin.fir" group = "org.jetbrains.kotlin.fir"
val jmhVersion = "1.21" val jmhVersion = "1.21"
val testDataPath = "$rootDir/compiler/fir/lightTree/testData/coroutines"
repositories { repositories {
mavenCentral() mavenCentral()
@@ -92,4 +98,17 @@ val jmhExec by tasks.creating(JavaExec::class) {
systemProperty("idea.home.path", project.intellij.localPath) systemProperty("idea.home.path", project.intellij.localPath)
systemProperty("idea.max.intellisense.filesize", 5000 * 1024) systemProperty("idea.max.intellisense.filesize", 5000 * 1024)
configurations.plusAssign(project.configurations["compile"]) configurations.plusAssign(project.configurations["compile"])
} }
val deleteGitFolder by tasks.creating(Delete::class) {
delete("$testDataPath/.git")
}
val cloneCoroutines by tasks.creating {
val url = "https://github.com/Kotlin/kotlinx.coroutines.git"
if (!File(testDataPath).exists()) {
Grgit.clone(mapOf("dir" to testDataPath,
"uri" to url)).close()
}
finalizedBy(tasks["deleteGitFolder"])
}
@@ -18,7 +18,11 @@ import org.jetbrains.kotlin.parsing.MyKotlinParser
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
class LightTree2Fir(private val stubMode: Boolean, private val parserDefinition: ParserDefinition, private val lexer: Lexer) { class LightTree2Fir(
private val stubMode: Boolean,
private val parserDefinition: ParserDefinition,
private val lexer: Lexer
) {
fun buildFirFile(path: Path): FirFile { fun buildFirFile(path: Path): FirFile {
return buildFirFile(path.toFile()) return buildFirFile(path.toFile())
} }
@@ -37,6 +41,7 @@ class LightTree2Fir(private val stubMode: Boolean, private val parserDefinition:
fun buildFirFile(code: String, fileName: String): FirFile { fun buildFirFile(code: String, fileName: String): FirFile {
val lightTree = buildLightTree(code) val lightTree = buildLightTree(code)
return Converter(object : FirSessionBase() {}, stubMode, lightTree).convertFile(lightTree.root, fileName) return Converter(object : FirSessionBase() {}, stubMode, lightTree)
.convertFile(lightTree.root, fileName)
} }
} }
@@ -18,6 +18,8 @@ import java.nio.file.Paths
@TestDataPath("\$PROJECT_ROOT") @TestDataPath("\$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners::class) @RunWith(JUnit3RunnerWithInners::class)
class LightTree2FirConverterTestCases : AbstractRawFirBuilderTestCase() { class LightTree2FirConverterTestCases : AbstractRawFirBuilderTestCase() {
private val testDirPath = "compiler/fir/psi2fir/testData/rawBuilder/declarations"
private fun executeTest(filePath: String) { private fun executeTest(filePath: String) {
val parserDefinition = KotlinParserDefinition() val parserDefinition = KotlinParserDefinition()
val lexer = parserDefinition.createLexer(myProject) val lexer = parserDefinition.createLexer(myProject)
@@ -31,78 +33,78 @@ class LightTree2FirConverterTestCases : AbstractRawFirBuilderTestCase() {
} }
fun testComplexTypes() { fun testComplexTypes() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/complexTypes.kt") executeTest("$testDirPath/complexTypes.kt")
} }
fun testDerivedClass() { fun testDerivedClass() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/derivedClass.kt") executeTest("$testDirPath/derivedClass.kt")
} }
fun testEnums() { fun testEnums() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/enums.kt") executeTest("$testDirPath/enums.kt")
} }
fun testEnums2() { fun testEnums2() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/enums2.kt") executeTest("$testDirPath/enums2.kt")
} }
fun testExpectActual() { fun testExpectActual() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/expectActual.kt") executeTest("$testDirPath/expectActual.kt")
} }
fun testF() { fun testF() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/F.kt") executeTest("$testDirPath/F.kt")
} }
fun testFunctionTypes() { fun testFunctionTypes() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/functionTypes.kt") executeTest("$testDirPath/functionTypes.kt")
} }
fun testGenericFunctions() { fun testGenericFunctions() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/genericFunctions.kt") executeTest("$testDirPath/genericFunctions.kt")
} }
fun testNestedClass() { fun testNestedClass() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/nestedClass.kt") executeTest("$testDirPath/nestedClass.kt")
} }
fun testNestedOfAliasedType() { fun testNestedOfAliasedType() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/NestedOfAliasedType.kt") executeTest("$testDirPath/NestedOfAliasedType.kt")
} }
fun testNestedSuperType() { fun testNestedSuperType() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/NestedSuperType.kt") executeTest("$testDirPath/NestedSuperType.kt")
} }
fun testNoPrimaryConstructor() { fun testNoPrimaryConstructor() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/noPrimaryConstructor.kt") executeTest("$testDirPath/noPrimaryConstructor.kt")
} }
fun testSimpleClass() { fun testSimpleClass() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/simpleClass.kt") executeTest("$testDirPath/simpleClass.kt")
} }
fun testSimpleFun() { fun testSimpleFun() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/simpleFun.kt") executeTest("$testDirPath/simpleFun.kt")
} }
fun testSimpleTypeAlias() { fun testSimpleTypeAlias() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/simpleTypeAlias.kt") executeTest("$testDirPath/simpleTypeAlias.kt")
} }
fun testTypeAliasWithGeneric() { fun testTypeAliasWithGeneric() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/typeAliasWithGeneric.kt") executeTest("$testDirPath/typeAliasWithGeneric.kt")
} }
fun testTypeParameterVsNested() { fun testTypeParameterVsNested() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/typeParameterVsNested.kt") executeTest("$testDirPath/typeParameterVsNested.kt")
} }
fun testTypeParameters() { fun testTypeParameters() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/typeParameters.kt") executeTest("$testDirPath/typeParameters.kt")
} }
fun testWhere() { fun testWhere() {
executeTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/where.kt") executeTest("$testDirPath/where.kt")
} }
} }
@@ -7,16 +7,20 @@ package org.jetbrains.kotlin.fir.lightTree.benchmark
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.openapi.vfs.CharsetToolkit
import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.TreeGenerator
import org.openjdk.jmh.annotations.* import org.openjdk.jmh.annotations.*
import java.io.File import java.io.File
import java.util.concurrent.TimeUnit
@BenchmarkMode(Mode.SingleShotTime) @BenchmarkMode(Mode.SingleShotTime)
@Warmup(iterations = 5, batchSize = 1) @Warmup(iterations = 10, batchSize = 1)
@Measurement(iterations = 5, batchSize = 1) @Measurement(iterations = 10, batchSize = 1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(1) @Fork(1)
open class AbstractBenchmark { @State(Scope.Benchmark)
abstract class AbstractBenchmark {
private val files = mutableMapOf<String, Pair<File, String>>() private val files = mutableMapOf<String, Pair<File, String>>()
abstract val generator: TreeGenerator
protected fun readFiles(ignoreTestData: Boolean, path: String) { protected fun readFiles(ignoreTestData: Boolean, path: String) {
val root = File(path) val root = File(path)
@@ -42,4 +46,8 @@ open class AbstractBenchmark {
f(text, file) f(text, file)
} }
} }
protected fun getFilesCount(): Int {
return files.size
}
} }
@@ -0,0 +1,35 @@
/*
* 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 org.openjdk.jmh.annotations.*
abstract class AbstractBenchmarkForGivenPath(
private val path: String,
private val ignoreTestData: Boolean = true
) : AbstractBenchmark() {
@Setup
fun setUp() {
generator.setUp()
readFiles(ignoreTestData, path)
println("FILES COUNT: ${getFilesCount()}")
}
@TearDown
fun tearDown() {
generator.tearDown()
}
@Benchmark
fun testBuildOnlyBaseTreeForGivenPath() {
forEachFile { text, file -> generator.generateBaseTree(text, file) }
}
@Benchmark
fun testBuildFirForGivenPath() {
forEachFile { text, file -> generator.generateFir(text, file) }
}
}
@@ -0,0 +1,20 @@
/*
* 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.coroutines
import org.jetbrains.kotlin.fir.lightTree.benchmark.AbstractBenchmarkForGivenPath
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.LightTree2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.Psi2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.TreeGenerator
abstract class AbstractCoroutinesBenchmark :
AbstractBenchmarkForGivenPath(System.getProperty("user.dir") + "/compiler/fir/lightTree/testData/coroutines", false)
open class LightTree2FirCoroutinesBenchmark(override val generator: TreeGenerator = LightTree2FirGenerator()) :
AbstractCoroutinesBenchmark()
open class Psi2FirCoroutinesBenchmark(override val generator: TreeGenerator = Psi2FirGenerator()) :
AbstractCoroutinesBenchmark()
@@ -6,16 +6,14 @@
package org.jetbrains.kotlin.fir.lightTree.benchmark.createdFiles package org.jetbrains.kotlin.fir.lightTree.benchmark.createdFiles
import org.jetbrains.kotlin.fir.lightTree.benchmark.* import org.jetbrains.kotlin.fir.lightTree.benchmark.*
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.LightTree2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.Psi2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.TreeGenerator
import org.openjdk.jmh.annotations.* import org.openjdk.jmh.annotations.*
import java.io.File import java.io.File
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@Warmup(iterations = 10, batchSize = 1, timeUnit = TimeUnit.NANOSECONDS)
@Measurement(iterations = 10, batchSize = 1, timeUnit = TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
abstract class AbstractKotlinBenchmark : AbstractBenchmark() { abstract class AbstractKotlinBenchmark : AbstractBenchmark() {
abstract val generator: TreeGenerator
@Param( @Param(
/* CLASSES */ /* CLASSES */
"1Class", "10Classes", "100Classes", "1000Classes", "10_000Classes", "100_000Classes", "1Class", "10Classes", "100Classes", "1000Classes", "10_000Classes", "100_000Classes",
@@ -0,0 +1,23 @@
/*
* 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.firModule
import org.jetbrains.kotlin.fir.lightTree.benchmark.*
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.LightTree2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.Psi2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.TreeGenerator
abstract class AbstractFirModuleBenchmark :
AbstractBenchmarkForGivenPath(
System.getProperty("user.dir") + "/compiler/fir",
true
)
open class LightTree2FirBenchmarkFirModule(override val generator: TreeGenerator = LightTree2FirGenerator()) :
AbstractFirModuleBenchmark()
open class Psi2FirBenchmarkFirModule(override val generator: TreeGenerator = Psi2FirGenerator()) :
AbstractFirModuleBenchmark()
@@ -3,7 +3,7 @@
* that can be found in the license/LICENSE.txt file. * that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.fir.lightTree.benchmark package org.jetbrains.kotlin.fir.lightTree.benchmark.generators
import com.intellij.psi.impl.DebugUtil import com.intellij.psi.impl.DebugUtil
import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.FirRenderer
@@ -16,15 +16,15 @@ import java.io.File
@State(Scope.Benchmark) @State(Scope.Benchmark)
open class LightTree2FirGenerator : TreeGenerator, AbstractRawFirBuilderTestCase() { open class LightTree2FirGenerator : TreeGenerator, AbstractRawFirBuilderTestCase() {
private var lightTreeConverter: LightTree2Fir? = null private lateinit var lightTreeConverter: LightTree2Fir
override fun generateBaseTree(text: String, file: File) { override fun generateBaseTree(text: String, file: File) {
val lightTree = lightTreeConverter!!.buildLightTree(text) val lightTree = lightTreeConverter.buildLightTree(text)
DebugUtil.lightTreeToString(lightTree, false) DebugUtil.lightTreeToString(lightTree, false)
} }
override fun generateFir(text: String, file: File) { override fun generateFir(text: String, file: File) {
val firFile = lightTreeConverter!!.buildFirFile(text, file.name) val firFile = lightTreeConverter.buildFirFile(text, file.name)
StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString() StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
} }
@@ -3,7 +3,7 @@
* that can be found in the license/LICENSE.txt file. * that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.fir.lightTree.benchmark package org.jetbrains.kotlin.fir.lightTree.benchmark.generators
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.impl.DebugUtil import com.intellij.psi.impl.DebugUtil
@@ -3,7 +3,7 @@
* that can be found in the license/LICENSE.txt file. * that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.fir.lightTree.benchmark package org.jetbrains.kotlin.fir.lightTree.benchmark.generators
import java.io.File import java.io.File
@@ -6,33 +6,13 @@
package org.jetbrains.kotlin.fir.lightTree.benchmark.totalKotlin package org.jetbrains.kotlin.fir.lightTree.benchmark.totalKotlin
import org.jetbrains.kotlin.fir.lightTree.benchmark.* import org.jetbrains.kotlin.fir.lightTree.benchmark.*
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.LightTree2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.Psi2FirGenerator
import org.jetbrains.kotlin.fir.lightTree.benchmark.generators.TreeGenerator
import org.openjdk.jmh.annotations.* import org.openjdk.jmh.annotations.*
@State(Scope.Benchmark) abstract class AbstractTotalKotlinBenchmark :
abstract class AbstractTotalKotlinBenchmark : AbstractBenchmark() { AbstractBenchmarkForGivenPath(System.getProperty("user.dir"))
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()) : open class LightTree2FirTotalKotlinBenchmark(override val generator: TreeGenerator = LightTree2FirGenerator()) :
AbstractTotalKotlinBenchmark() AbstractTotalKotlinBenchmark()