How can I use JMH to benchmark a specific part of a method

321 views Asked by At

I'm looking for a way to benchmark a specific for-loop inside a method. The for-loop cannot be extracted and have its state initialized/mocked.

  void method(ScheduledExecutorService exec) throws Exception {
    File testFile = new File("./test");
    Collection<Future> futures = new HashSet<>();
    testFile.createNewFile();
    for (int i = 0; i < 50; i++) {
      final int j = i;
      final Future<?> future = exec.submit(() -> {
        Files.write(("Test-" + j).getBytes(StandardCharsets.UTF_8), testFile);
      });
      futures.add(future);
    }
    // BENCHMARK HERE
    for (Future future : futures) {
      future.get();
    }
  }

Notice that I'm looking to benchmark only the future.get() part, using JMH. My research shows that JMH is like JUnit, i.e. it discovers @Benchmark annotated methods and runs those with a clean state, and also starts a new JVM process to run those benchmarks, which means we can't provide the Collection<Future> as state to a benchmarked method.

Yes I understand that I shouldn't benchmark File I/O but someone else is asking for JMH to be used instead of System.currentTimeMillis so I'm looking to see if this is even possible before going back to block this requirement.

1

There are 1 answers

0
Sergey Tsypanov On BEST ANSWER

JMH is method-based framework, i.e. it measures performance of a method annotated with @Benchmark, so in your case there's no other way but to split the logic. Everything before the loop should be moved into @Setup-annotated method and the the loop into @Benchmark-annotated one. Pay attention, that in this case JMH must be run in single-shot mode or @Setup must be set into Invocation mode to have the futures recreated for each measurement.