Bhuwan Upadhyay

Talks all about software engineering

Published on

How to use jmh with spring boot



Application performance is a concern of every developer working with software. JMH provides an easy API for developer to benchmark application performance.

In this post, I’ll walk you through to how to use jmh with spring boot. You’ll learn how to set up Spring Boot Test and how to enable jmh benchmark in your test code.

Create a Spring Boot Project

curl https://start.spring.io/starter.tgz -d dependencies=h2,data-jpa,data-rest,lombok \
  -d groupId=io.github.bhuwanupadhyay \
  -d artifactId=example \
  -d packageName=io.github.bhuwanupadhyay.tutorial \
  -d baseDir=example \
  -d bootVersion=2.2.2.RELEASE | tar -xzvf -
cd example

Add JMH dependencies in pom.xml


Let's add some classes for benchmark

  • OrderLine entity class
@ToString(exclude = {"itemId", "addressLine", "quantity"})
@EqualsAndHashCode(exclude = {"itemId", "addressLine", "quantity"})
class OrderLine implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Long itemId;
    private String addressLine;
    private Integer quantity;

  • OrderLineRepository repository class for an entity OrderLine
interface OrderLineRepository extends JpaRepository<OrderLine, Long> {
  • The spring boot configuration application.properties

JMH Benchmark Code

Let's benchmark insert operation for OrderLine entity into database.

@Spring BootTest
public class DemoApplicationTests {

 private static OrderLineRepository repository;
 public void setRepository(OrderLineRepository repository) {
  DemoApplicationTests.repository = repository;

 public void runBenchmarks() throws Exception {
  Options opts = new OptionsBuilder()
    // set the class name regex for benchmarks to search for to the current class
    .include("\\." + this.getClass().getSimpleName() + "\\.")
    // do not use forking or the benchmark methods will not see references stored within its class
    // do not use multiple threads
  new Runner(opts).run();

 public void dbInserts(Parameters parameters) {
  int size = Integer.parseInt(parameters.batchSize);
  for (int i = 0; i < size; i++) {
   OrderLine line = new OrderLine();
   line.setAddressLine("Jhamsikhel Ward #3, Arun Thapa Chwok, Lalitpur, Nepal");

 @State(value = Scope.Benchmark)
 public static class Parameters {
  @Param({"1", "1000"})
  String batchSize;

Benchmark Result for this example