diff --git a/compiler/fir/lightTree/build.gradle.kts b/compiler/fir/lightTree/build.gradle.kts index f985d0d6b59..68838541905 100644 --- a/compiler/fir/lightTree/build.gradle.kts +++ b/compiler/fir/lightTree/build.gradle.kts @@ -90,5 +90,6 @@ val jmhExec by tasks.creating(JavaExec::class) { workingDir = rootDir systemProperty("idea.home.path", project.intellij.localPath) + systemProperty("idea.max.intellisense.filesize", 5000 * 1024) configurations.plusAssign(project.configurations["compile"]) } \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/AbstractKotlinBenchmark.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/AbstractKotlinBenchmark.kt new file mode 100644 index 00000000000..e65f029eda3 --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/AbstractKotlinBenchmark.kt @@ -0,0 +1,66 @@ +/* + * 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.createdFiles + +import org.jetbrains.kotlin.fir.lightTree.benchmark.* +import org.openjdk.jmh.annotations.* +import java.io.File +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 val generator: TreeGenerator + + @Param( + /* CLASSES */ + "1Class", "10Classes", "100Classes", "1000Classes", "10_000Classes", "100_000Classes", + "1Cin1C", "10Cin1C", "100Cin1C", "1000Cin1C", "10_000Cin1C", "100_000Cin1C", + "1Cin10C", "10Cin10C", "100Cin10C", "1000Cin10C", "10_000Cin10C", + "1Cin100C", "10Cin100C", "100Cin100C", "1000Cin100C", + "1Cin1000C", "10Cin1000C", "100Cin1000C", + "1Cin10_000C", "10Cin10_000C", "1Cin100_000C", + /* FUNCTIONS */ + "1Fun", "10Fun", "100Fun", "1000Fun", "10_000Fun", "100_000Fun", + "1Fin1C", "1Fin10C", "1Fin100C", "1Fin1000C", "1Fin10_000C", "1Fin100_000C", + "10Fin1C", "10Fin10C", "10Fin100C", "10Fin1000C", "10Fin10_000C", + "100Fin1C", "100Fin10C", "100Fin100C", "100Fin1000C", + /* PROPERTIES */ + "1Var", "10Var", "100Var", "1000Var", "10_000Var", "100_000Var", + "1Vin1C", "1Vin10C", "1Vin100C", "1Vin1000C", "1Vin10_000C", "1Vin100_000C", + "10Vin1C", "10Vin10C", "10Vin100C", "10Vin1000C", "10Vin10_000C", + "100Vin1C", "100Vin10C", "100Vin100C", "100Vin1000C" + ) + var methodName: String = "" + + private var text: String = "" + private var file: File = File("$methodName.kt") + + @Setup + fun setUp() { + generator.setUp() + + val testMethod = TestCases::class.java.getMethod(methodName) + text = testMethod.invoke(TestCases()) as String + } + + @TearDown + fun tearDown() { + generator.tearDown() + } + + @Benchmark + fun testCreatedFiles() { + generator.generateFir(text, file) + } +} + +open class LightTree2FirKotlinBenchmark(override val generator: TreeGenerator = LightTree2FirGenerator()) : + AbstractKotlinBenchmark() + +open class Psi2FirKotlinBenchmark(override val generator: TreeGenerator = Psi2FirGenerator()) : + AbstractKotlinBenchmark() \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCases.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCases.kt new file mode 100644 index 00000000000..bf33eb8b27e --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCases.kt @@ -0,0 +1,542 @@ +/* + * 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.createdFiles + +class TestCases { + /* CLASSES */ + fun `1Class`(): String { + return TestCasesGenerator().generateData({ createClass(1) }).getText() + } + + fun `10Classes`(): String { + return TestCasesGenerator().generateData({ createClass(10) }).getText() + } + + fun `100Classes`(): String { + return TestCasesGenerator().generateData({ createClass(100) }).getText() + } + + fun `1000Classes`(): String { + return TestCasesGenerator().generateData({ createClass(1000) }).getText() + } + + fun `10_000Classes`(): String { + return TestCasesGenerator().generateData({ createClass(10000) }).getText() + } + + fun `100_000Classes`(): String { + return TestCasesGenerator().generateData({ createClass(100000) }).getText() + } + + fun `1Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(1) + }) + }).getText() + } + + fun `10Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(10) + }) + }).getText() + } + + fun `100Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(100) + }) + }).getText() + } + + fun `1000Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(1000) + }) + }).getText() + } + + fun `10_000Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(10_000) + }) + }).getText() + } + + fun `100_000Cin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createClass(100_000) + }) + }).getText() + } + + fun `1Cin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createClass(1) + }) + }).getText() + } + + fun `10Cin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createClass(10) + }) + }).getText() + } + + fun `100Cin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createClass(100) + }) + }).getText() + } + + fun `1000Cin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createClass(1000) + }) + }).getText() + } + + fun `10_000Cin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createClass(10_000) + }) + }).getText() + } + + fun `1Cin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createClass(1) + }) + }).getText() + } + + fun `10Cin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createClass(10) + }) + }).getText() + } + + fun `100Cin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createClass(100) + }) + }).getText() + } + + fun `1000Cin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createClass(1000) + }) + }).getText() + } + + fun `1Cin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createClass(1) + }) + }).getText() + } + + fun `10Cin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createClass(10) + }) + }).getText() + } + + fun `100Cin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createClass(100) + }) + }).getText() + } + + fun `1Cin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createClass(1) + }) + }).getText() + } + + fun `10Cin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createClass(10) + }) + }).getText() + } + + fun `1Cin100_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100_000, { + createClass(1) + }) + }).getText() + } + + /* FUNCTIONS */ + fun `1Fun`(): String { + return TestCasesGenerator().generateData({ createFun(1) }).getText() + } + + fun `10Fun`(): String { + return TestCasesGenerator().generateData({ createFun(10) }).getText() + } + + fun `100Fun`(): String { + return TestCasesGenerator().generateData({ createFun(100) }).getText() + } + + fun `1000Fun`(): String { + return TestCasesGenerator().generateData({ createFun(1000) }).getText() + } + + fun `10_000Fun`(): String { + return TestCasesGenerator().generateData({ createFun(10000) }).getText() + } + + fun `100_000Fun`(): String { + return TestCasesGenerator().generateData({ createFun(100000) }).getText() + } + + fun `1Fin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createFun(1) + }) + }).getText() + } + + fun `1Fin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createFun(1) + }) + }).getText() + } + + fun `1Fin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createFun(1) + }) + }).getText() + } + + fun `1Fin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createFun(1) + }) + }).getText() + } + + fun `1Fin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createFun(1) + }) + }).getText() + } + + fun `1Fin100_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100_000, { + createFun(1) + }) + }).getText() + } + + fun `10Fin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createFun(10) + }) + }).getText() + } + + fun `10Fin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createFun(10) + }) + }).getText() + } + + fun `10Fin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createFun(10) + }) + }).getText() + } + + fun `10Fin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createFun(10) + }) + }).getText() + } + + fun `10Fin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createFun(10) + }) + }).getText() + } + + fun `100Fin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createFun(100) + }) + }).getText() + } + + fun `100Fin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createFun(100) + }) + }).getText() + } + + fun `100Fin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createFun(100) + }) + }).getText() + } + + fun `100Fin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createFun(100) + }) + }).getText() + } + + /* PROPERTIES */ + fun `1Var`(): String { + return TestCasesGenerator().generateData({ createProperty(1) }).getText() + } + + fun `10Var`(): String { + return TestCasesGenerator().generateData({ createProperty(10) }).getText() + } + + fun `100Var`(): String { + return TestCasesGenerator().generateData({ createProperty(100) }).getText() + } + + fun `1000Var`(): String { + return TestCasesGenerator().generateData({ createProperty(1000) }).getText() + } + + fun `10_000Var`(): String { + return TestCasesGenerator().generateData({ createProperty(10000) }).getText() + } + + fun `100_000Var`(): String { + return TestCasesGenerator().generateData({ createProperty(100000) }).getText() + } + + fun `1Vin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createProperty(1) + }) + }).getText() + } + + fun `1Vin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createProperty(1) + }) + }).getText() + } + + fun `1Vin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createProperty(1) + }) + }).getText() + } + + fun `1Vin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createProperty(1) + }) + }).getText() + } + + fun `1Vin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createProperty(1) + }) + }).getText() + } + + fun `1Vin100_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100_000, { + createProperty(1) + }) + }).getText() + } + + fun `10Vin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createProperty(10) + }) + }).getText() + } + + fun `10Vin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createProperty(10) + }) + }).getText() + } + + fun `10Vin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createProperty(10) + }) + }).getText() + } + + fun `10Vin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createProperty(10) + }) + }).getText() + } + + fun `10Vin10_000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10_000, { + createProperty(10) + }) + }).getText() + } + + fun `100Vin1C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1, { + createProperty(100) + }) + }).getText() + } + + fun `100Vin10C`(): String { + return TestCasesGenerator().generateData( + { + createClass(10, { + createProperty(100) + }) + }).getText() + } + + fun `100Vin100C`(): String { + return TestCasesGenerator().generateData( + { + createClass(100, { + createProperty(100) + }) + }).getText() + } + + fun `100Vin1000C`(): String { + return TestCasesGenerator().generateData( + { + createClass(1000, { + createProperty(100) + }) + }).getText() + } +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCasesGenerator.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCasesGenerator.kt new file mode 100644 index 00000000000..56b99c21966 --- /dev/null +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/benchmark/createdFiles/TestCasesGenerator.kt @@ -0,0 +1,99 @@ +/* + * 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.createdFiles + +import org.jetbrains.kotlin.utils.Printer +import kotlin.random.Random + +class TestCasesGenerator { + private val charPool: List = ('a'..'z') + ('A'..'Z') + private val types = listOf("Int", "Double", "Boolean", "String") + + private val builder = StringBuilder() + private val printer: Printer + + init { + printer = Printer(builder, " ") + } + + fun generateData(vararg pipeline: TestCasesGenerator.() -> Unit): TestCasesGenerator { + printer.apply { + pipeline.forEach { it() } + } + return this + } + + fun createClass(count: Int, vararg pipeline: TestCasesGenerator.() -> Unit) { + for (i in 1..count) { + printer.println("class ${randomString(Random.nextLong(5, 15))} {") + printer.pushIndent() + printer.apply { + pipeline.forEach { it() } + } + printer.popIndent() + printer.println("}") + } + } + + fun createFun(count: Int, vararg pipeline: TestCasesGenerator.() -> Unit) { + for (i in 1..count) { + printer.println("fun ${randomString(Random.nextLong(5, 15))}() {") + printer.pushIndent() + printer.apply { + pipeline.forEach { it() } + } + printer.popIndent() + printer.println("}") + } + } + + fun createProperty(count: Int) { + for (i in 1..count) { + val typeAndValue = getRandomTypeAndValue() + printer.println( + "val ${randomString(Random.nextLong(5, 15))}: " + + "${typeAndValue.first} = ${typeAndValue.second} \n" + ) + } + } + + private fun randomString(length: Long): String { + return (1..length) + .map { Random.nextInt(0, charPool.size) } + .map(charPool::get) + .joinToString("") + } + + private fun getRandomTypeAndValue(): Pair { + val type = types[Random.nextInt(0, types.size)] + return when (type) { + "Int" -> Pair(type, Random.nextInt().toString()) + "Double" -> Pair(type, Random.nextDouble().toString()) + "Boolean" -> Pair(type, Random.nextBoolean().toString()) + "String" -> Pair(type, randomString(Random.nextLong(5, 15))) + else -> throw UnsupportedOperationException("Unsupported type") + } + } + + fun getText(): String { + return builder.toString() + } +} + +fun main() { + TestCasesGenerator().generateData( + { + createClass(10, + { + createClass(100, + { + createClass(100) + }) + }) + } + ) +} +