Create benchmarks for your Java codebase using Java Microbenchmark Harness
The Java integration is still in early development, and only the walltime
instrument is currently supported.If you have any feedback, please reach out to us via
Discord or
email our support.
Integrating CodSpeed into your Java project works through a fork of
JMH (Java Microbenchmark Harness). You write
standard JMH benchmarks and swap in the CodSpeed JMH fork as a dependency. When
running in CI with CodSpeed, the results are automatically collected and
reported.
Then replace the JMH dependencies in your pom.xml with the CodSpeed fork.
Maven resolves from ~/.m2/repository by default. The repository entry below is
only necessary if your local repository is at a non-default location:
Write your benchmarks using standard JMH annotations:
FibBenchmark.java
package bench;import org.openjdk.jmh.annotations.*;public class FibBenchmark { @Benchmark public long fib() { return fib(30); } private static long fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); }}
JMH benchmarks must return their result or use Blackhole.consume() to
prevent the JVM from eliminating dead code. All examples on this page return
the computed value.
For more information on how to write benchmarks with JMH, check out the
official JMH
samples.
To generate performance reports, you need to run the benchmarks in your CI. This
allows CodSpeed to automatically run benchmarks and warn you about regressions
during development.
If you want more details on how to configure the CodSpeed action, you can check
out the Continuous Reporting section.
Here is an example of a GitHub Actions workflow that runs the benchmarks and
reports the results to CodSpeed on every push to the main branch and every
pull request:
JMH provides many features for writing expressive benchmarks. Below is a
selection that can be useful in CodSpeed benchmarks, but check out the
official JMH samples
for an exhaustive list of features.
Use @State to share setup logic across benchmarks and control the scope of the
state object:
StateBenchmark.java
package bench;import org.openjdk.jmh.annotations.*;import java.util.ArrayList;import java.util.List;@State(Scope.Benchmark)public class StateBenchmark { List<Integer> list; @Setup public void setup() { list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { list.add(i); } } @Benchmark public int sum() { return list.stream().mapToInt(Integer::intValue).sum(); }}