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.
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.