Benchmarking in Java | Generated by AI

Home PDF

The Java Microbenchmark Harness (JMH) is a powerful tool for building, running, and analyzing microbenchmarks in Java. It allows developers to measure the performance of their code in a controlled and repeatable way. Below is a comprehensive guide on how to use JMH effectively.


1. Set Up Your Project

To use JMH, you need to include it in your project. Here’s how to do it with Maven or Gradle:

Maven

Add the following dependencies to your pom.xml:

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.36</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.36</version>
    <scope>provided</scope>
</dependency>

Gradle

Add these lines to your build.gradle:

dependencies {
    implementation 'org.openjdk.jmh:jmh-core:1.36'
    annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.36'
}

These dependencies provide the JMH core library and the annotation processor needed to generate benchmark code.


2. Write Your Benchmark

Create a Java class to define your benchmark. Use the @Benchmark annotation to mark the methods you want to measure. Here’s a simple example:

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import java.util.concurrent.TimeUnit;

public class MyBenchmark {

    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public void testMethod() {
        // Code to benchmark
        int a = 1;
        int b = 2;
        int sum = a + b;
    }
}

3. Configure the Benchmark

You can customize your benchmark using additional JMH annotations:

Example with configuration:

@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
public class MyBenchmark {
    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void testMethod() {
        // Code to benchmark
    }
}

4. Run the Benchmark

To execute your benchmark, you can use the JMH runner. Here’s how to do it with Maven:

Add the Maven Shade Plugin

Include this in your pom.xml to create an executable JAR:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <finalName>benchmarks</finalName>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>org.openjdk.jmh.Main</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Build and Run

  1. Build the JAR: mvn clean package
  2. Run the benchmark: java -jar target/benchmarks.jar

JMH will execute the benchmarks and display the results in your terminal.


5. Analyze the Results

JMH outputs performance metrics based on your configuration. For example:

Benchmark              Mode  Cnt  Score   Error  Units
MyBenchmark.testMethod avgt    5  1.234 ± 0.012  ns/op

Use these results to evaluate and optimize your code’s performance.


6. Advanced Features

JMH offers additional tools for more complex scenarios:

Parameterization

Test your code with different inputs using @Param:

@State(Scope.Benchmark)
public class MyBenchmark {
    @Param({"1", "10", "100"})
    private int iterations;

    @Benchmark
    public void testMethod() {
        for (int i = 0; i < iterations; i++) {
            // Code to benchmark
        }
    }
}

Blackholes

Prevent the JVM from optimizing away unused results with Blackhole:

@Benchmark
public void testMethod(Blackhole bh) {
    int sum = 1 + 2;
    bh.consume(sum); // Prevents dead code elimination
}

7. Best Practices


By following these steps, you can use org.openjdk.jmh to accurately measure and improve the performance of your Java code. Whether you’re testing simple operations or complex algorithms, JMH provides the tools you need for reliable benchmarking.


Back 2025.03.06 Donate