# Setting Up Kotlin/JVM and Java Projects for Benchmarking In this guide, we'll take you through the steps to set up a Kotlin/JVM or Java project for benchmarking using `kotlinx-benchmark`. ## Step-by-step Setup Guide To configure Kotlin/JVM and Java projects for benchmarking, follow these steps: 1. Apply the benchmark plugin:
Kotlin DSL ```kotlin // build.gradle.kts plugins { id("org.jetbrains.kotlinx.benchmark") version "0.4.13" } ```
Groovy DSL ```groovy // build.gradle plugins { id 'org.jetbrains.kotlinx.benchmark' version '0.4.13' } ```
2. Make sure to include the Gradle Plugin Portal for plugin lookup in the list of repositories:
Kotlin DSL ```kotlin // settings.gradle.kts pluginManagement { repositories { gradlePluginPortal() } } ```
Groovy DSL ```groovy // settings.gradle pluginManagement { repositories { gradlePluginPortal() } } ```
3. Next, add the `kotlinx-benchmark-runtime` dependency to the project:
Kotlin DSL ```kotlin // build.gradle.kts dependencies { implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.13") } ```
Groovy DSL ```groovy // build.gradle dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.13' } ```
4. Include Maven Central in the list of repositories for dependency lookup:
Kotlin DSL ```kotlin // build.gradle.kts repositories { mavenCentral() } ```
Groovy DSL ```groovy // build.gradle repositories { mavenCentral() } ```
5. Apply [allopen plugin](https://kotlinlang.org/docs/all-open-plugin.html) if you have benchmark classes in Kotlin:
Kotlin DSL ```kotlin // build.gradle.kts plugins { kotlin("plugin.allopen") version "2.0.20" } allOpen { annotation("org.openjdk.jmh.annotations.State") } ```
Groovy DSL ```groovy // build.gradle plugins { id 'org.jetbrains.kotlin.plugin.allopen' version "2.0.20" } allOpen { annotation("org.openjdk.jmh.annotations.State") } ```
Explanation Assume that you've annotated each of your benchmark classes with `@State(Scope.Benchmark)`: ```kotlin // MyBenchmark.kt @State(Scope.Benchmark) class MyBenchmark { // Benchmarking-related methods and variables @Benchmark fun benchmarkMethod() { // benchmarking logic } } ``` In Kotlin, classes are `final` by default, which means they can't be overridden. This conflicts with the Java Microbenchmark Harness (JMH) operation, which `kotlinx-benchmark` uses under the hood for running benchmarks on JVM. JMH requires benchmark classes and methods to be `open` to be able to generate subclasses and conduct the benchmark. This is where the `allopen` plugin comes into play. With the plugin applied, any class annotated with `@State` is treated as `open`, which allows JMH to work as intended: ```kotlin // build.gradle.kts plugins { kotlin("plugin.allopen") version "2.0.20" } allOpen { annotation("org.openjdk.jmh.annotations.State") } ``` This configuration ensures that your `MyBenchmark` class and its `benchmarkMethod` function are treated as `open`.
You can alternatively mark your benchmark classes and methods `open` manually, but using the `allopen` plugin enhances code maintainability. 6. Designate the `main` source set as a benchmark target:
Kotlin DSL ```kotlin // build.gradle.kts benchmark { targets { register("main") } } ```
Groovy DSL ```kotlin // build.gradle benchmark { targets { register("main") } } ```
This informs the `kotlinx-benchmark` tool that benchmarks reside within `main` source set. ## Writing Benchmarks After completing the setup of your project, you're ready to dive into writing benchmarks. `kotlinx-benchmark` leverages the Java Microbenchmark Harness (JMH) toolkit to execute benchmarks on the JVM. As a result, it automatically includes the necessary dependency on JMH, allowing you to harness its API for crafting benchmarks: ```kotlin import org.openjdk.jmh.annotations.* import java.util.concurrent.* import kotlin.math.cos import kotlin.math.sqrt import kotlin.random.Random @State(Scope.Benchmark) @Fork(1) @Warmup(iterations = 10) @Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) class MyBenchmark { private var data = 0.0 @Setup fun setUp() { data = Random.nextDouble() } @Benchmark fun sqrtBenchmark(): Double { return sqrt(data) } @Benchmark fun cosBenchmark(): Double { return cos(data) } } ``` See [writing benchmarks](writing-benchmarks.md) for a complete guide for writing benchmarks. ### Running Benchmarks To run your benchmarks, run `benchmark` Gradle task in the project. In the terminal, navigate to the project's root directory and run `./gradlew benchmark`. For more details about the tasks created by the `kotlinx-benchmark` plugin, refer to [this guide](tasks-overview.md). ### Benchmark Configuration Profiles The `kotlinx-benchmark` library provides the ability to create multiple configuration profiles. The `main` configuration is already created by the toolkit. Additional profiles can be created as needed in the `configurations` section of the `benchmark` block: ```kotlin // build.gradle.kts benchmark { configurations { named("main") { warmups = 20 iterations = 10 iterationTime = 3 iterationTimeUnit = "s" } register("smoke") { include("") warmups = 5 iterations = 3 iterationTime = 500 iterationTimeUnit = "ms" } } } ``` Refer to our [comprehensive guide](configuration-options.md) to learn about configuration options and how they affect benchmark execution. ### Separate source set for benchmarks Often you want to have benchmarks in the same project, but separated from main code, much like tests. Refer to our [detailed documentation](separate-benchmark-source-set.md) on configuring your project to set up a separate source set for benchmarks. ## Examples Explore sample [Kotlin/JVM](/examples/kotlin-jvm) and [Java](/examples/java) benchmarking projects that use `kotlinx-benchmark`. These examples showcase how to structure benchmarking projects using `kotlinx-benchmark`.