From f8c0e3e1aeb7d900a79e0bf6fc0ba0d188fb44c2 Mon Sep 17 00:00:00 2001 From: Filipp Zhinkin Date: Thu, 25 Jan 2024 11:12:02 +0100 Subject: [PATCH 1/4] Add a test that explicitly sets up a toolchain --- .../benchmark/integration/GradleTest.kt | 5 +++- .../integration/JvmToolchainsTest.kt | 12 +++++++++ .../templates/kmp-with-toolchain/build.gradle | 25 +++++++++++++++++++ .../kmp-with-toolchain/gradle.properties | 1 + .../kmp-with-toolchain/settings.gradle | 3 +++ .../src/commonMain/kotlin/CommonBenchmark.kt | 15 +++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt create mode 100644 integration/src/test/resources/templates/kmp-with-toolchain/build.gradle create mode 100644 integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties create mode 100644 integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle create mode 100644 integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt index 14b1c94d..6d6551c5 100644 --- a/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt @@ -26,7 +26,10 @@ abstract class GradleTest { val builder = ProjectBuilder().apply(build) templates.resolve(name).copyRecursively(rootProjectDir) file("build.gradle").modify(builder::build) - file("settings.gradle").writeText("") // empty settings file + val settingsFile = file("settings.gradle") + if (!settingsFile.exists()) { + file("settings.gradle").writeText("") // empty settings file + } return Runner(rootProjectDir, print, gradleVersion) } } diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt new file mode 100644 index 00000000..5dd02d4d --- /dev/null +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt @@ -0,0 +1,12 @@ +package kotlinx.benchmark.integration + +import org.junit.Test + +class JvmToolchainsTest : GradleTest() { + @Test + fun testJvmToolchainSetup() { + val runner = project("kmp-with-toolchain", true, GradleTestVersion.v8_0) { + } + runner.run("jvmBenchmark") + } +} diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle new file mode 100644 index 00000000..79e4e8a5 --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle @@ -0,0 +1,25 @@ +kotlin { + jvm { + compilations.create('benchmark') { associateWith(compilations.main) } + jvmToolchain(21) + } + + sourceSets { + commonMain { + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.5.0-SNAPSHOT") + } + } + jvmMain { + } + jvmBenchmark { + dependsOn(jvmMain) + } + } +} + +benchmark { + targets { + register("jvm") + } +} diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties b/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties new file mode 100644 index 00000000..7ec1fb65 --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 \ No newline at end of file diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle b/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle new file mode 100644 index 00000000..1791349e --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle @@ -0,0 +1,3 @@ +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt b/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt new file mode 100644 index 00000000..1174ed76 --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt @@ -0,0 +1,15 @@ +package test + +import kotlinx.benchmark.* +import kotlin.math.* + +// Don't really need to measure anything here, just check that the benchmark works +@State(Scope.Benchmark) +@Warmup(iterations = 0) +@Measurement(iterations = 1, time = 100, timeUnit = BenchmarkTimeUnit.MILLISECONDS) +@OutputTimeUnit(BenchmarkTimeUnit.MILLISECONDS) +@BenchmarkMode(Mode.Throughput) +open class CommonBenchmark { + @Benchmark + open fun mathBenchmark() = 3.14 +} From bdd6b34cbe75359ca528a6500b20400909666bfc Mon Sep 17 00:00:00 2001 From: Filipp Zhinkin Date: Thu, 25 Jan 2024 11:33:32 +0100 Subject: [PATCH 2/4] Use configured toolchain for JMH tasks --- .../gradle/JmhBytecodeGeneratorTask.kt | 8 ++++++++ .../src/kotlinx/benchmark/gradle/JvmTasks.kt | 5 +++++ .../src/kotlinx/benchmark/gradle/Utils.kt | 19 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt b/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt index 7edef37d..51151864 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt @@ -2,6 +2,7 @@ package kotlinx.benchmark.gradle import org.gradle.api.* import org.gradle.api.file.* +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.workers.* import java.io.* @@ -28,11 +29,18 @@ open class JmhBytecodeGeneratorTask @InputFiles @PathSensitive(PathSensitivity.RELATIVE) lateinit var runtimeClasspath: FileCollection + + @Optional + @Input + var executableProvider: Provider = project.provider { null } @TaskAction fun generate() { val workQueue = workerExecutor.processIsolation { workerSpec -> workerSpec.classpath.setFrom(runtimeClasspath.files) + if (executableProvider.isPresent) { + workerSpec.forkOptions.executable = executableProvider.get() + } } workQueue.submit(JmhBytecodeGeneratorWorker::class.java) { workParameters -> workParameters.inputClasses.setFrom(inputClassesDirs.files) diff --git a/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt b/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt index f10fd38b..5add7ad7 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt @@ -20,6 +20,7 @@ fun Project.createJvmBenchmarkCompileTask(target: JvmBenchmarkTarget, compileCla classpath = compileClasspath source = fileTree("$benchmarkBuildDir/sources") destinationDirectory.set(file("$benchmarkBuildDir/classes")) + javaCompiler.set(javaCompilerProvider()) } task( @@ -90,6 +91,9 @@ fun Project.createJvmBenchmarkGenerateSourceTask( inputClassesDirs = compilationOutput outputResourcesDir = file("$benchmarkBuildDir/resources") outputSourcesDir = file("$benchmarkBuildDir/sources") + executableProvider = javaLauncherProvider().map { + it.executablePath.asFile.absolutePath + } } } @@ -123,5 +127,6 @@ fun Project.createJvmBenchmarkExecTask( val reportFile = setupReporting(target, config) args(writeParameters(target.name, reportFile, traceFormat(), config)) + javaLauncher.set(javaLauncherProvider()) } } diff --git a/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt b/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt index c07d4a11..500e0459 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt @@ -5,7 +5,12 @@ import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider +import org.gradle.jvm.toolchain.JavaCompiler +import org.gradle.jvm.toolchain.JavaLauncher +import org.gradle.jvm.toolchain.JavaToolchainService import java.io.File import java.nio.file.Path import java.time.LocalDateTime @@ -261,4 +266,16 @@ internal fun Project.getSystemProperty(key: String): String? { } else { System.getProperty(key) } -} \ No newline at end of file +} + +fun Project.javaCompilerProvider(): Provider = provider { + val toolchainService = extensions.findByType(JavaToolchainService::class.java) ?: return@provider null + val javaExtension = extensions.findByType(JavaPluginExtension::class.java) ?: return@provider null + toolchainService.compilerFor(javaExtension.toolchain).orNull +} + +fun Project.javaLauncherProvider(): Provider = provider { + val toolchainService = extensions.findByType(JavaToolchainService::class.java) ?: return@provider null + val javaExtension = extensions.findByType(JavaPluginExtension::class.java) ?: return@provider null + toolchainService.launcherFor(javaExtension.toolchain).orNull +} From b1a9be2dec80d645925c932bd350376953f7b27d Mon Sep 17 00:00:00 2001 From: Filipp Zhinkin Date: Tue, 6 Feb 2024 10:16:39 +0100 Subject: [PATCH 3/4] Cleaned up the test project --- .../resources/templates/kmp-with-toolchain/build.gradle | 6 ------ 1 file changed, 6 deletions(-) diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle index 79e4e8a5..f35e0edf 100644 --- a/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle +++ b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle @@ -1,6 +1,5 @@ kotlin { jvm { - compilations.create('benchmark') { associateWith(compilations.main) } jvmToolchain(21) } @@ -10,11 +9,6 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.5.0-SNAPSHOT") } } - jvmMain { - } - jvmBenchmark { - dependsOn(jvmMain) - } } } From 74e4dd5e479e80ec581f380965f989abe8b408b4 Mon Sep 17 00:00:00 2001 From: Filipp Zhinkin Date: Tue, 6 Feb 2024 10:17:29 +0100 Subject: [PATCH 4/4] Strengthen the test assertions --- .../benchmark/integration/JvmToolchainsTest.kt | 7 ++++++- .../kotlin/kotlinx/benchmark/integration/testDsl.kt | 12 +++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt index 5dd02d4d..645505dd 100644 --- a/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt @@ -1,12 +1,17 @@ package kotlinx.benchmark.integration +import org.gradle.testkit.runner.TaskOutcome import org.junit.Test +import kotlin.test.assertEquals class JvmToolchainsTest : GradleTest() { @Test fun testJvmToolchainSetup() { val runner = project("kmp-with-toolchain", true, GradleTestVersion.v8_0) { } - runner.run("jvmBenchmark") + runner.run("benchmark") { + assertEquals(TaskOutcome.SUCCESS, task(":jvmBenchmark")!!.outcome) + assertOutputDoesNotContain("") + } } } diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt index d301e624..75666a1f 100644 --- a/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt @@ -45,4 +45,14 @@ internal fun BuildResult.assertOutputContains( } } -internal fun BuildResult.assertTasksUpToDate(tasks: Collection) = assertTasksUpToDate(*tasks.toTypedArray()) \ No newline at end of file +internal fun BuildResult.assertOutputDoesNotContain( + expectedSubString: String, + message: String = "Build output contains \"$expectedSubString\"" +) { + assert(!output.contains(expectedSubString)) { + printBuildOutput() + message + } +} + +internal fun BuildResult.assertTasksUpToDate(tasks: Collection) = assertTasksUpToDate(*tasks.toTypedArray())