Usage of Blackhole in a loop distorts benchmark results
Сергей Цыпанов
sergei.tsypanov at yandex.ru
Wed Jan 17 07:47:30 UTC 2018
Say I have this benchmark:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-XX:+UseParallelGC", "-Xms2g", "-Xmx2g"})
public class IteratorFromStreamBenchmark {
@Benchmark
public void iteratorFromStream(Data data, Blackhole bh) {
Iterator<Integer> iterator = data.items.stream()
.iterator();
while (iterator.hasNext())
bh.consume(iterator.next());
}
@Benchmark
public void forEach(Data data, Blackhole bh) {
data.items.stream().forEach(bh::consume);
}
@State(Scope.Thread)
public static class Data {
private Collection<Integer> items;
private int size = 1000;
@Setup
public void init() {
items = IntStream.range(0, size).boxed().collect(toList());
}
}
}
which on Java 9 (JDK 9, VM 9+181) yields this output:
Benchmark Mode Cnt Score Error Units
forEach avgt 100 6130,066 ± 308,597 ns/op
iteratorFromStream avgt 100 4835,355 ± 57,886 ns/op
Here 'iteratorFromStream' appears to be faster than 'forEach'
Then I change the behaviour to accumulate the result of iteration over elements and return it:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-XX:+UseParallelGC", "-Xms2g", "-Xmx2g"})
public class IteratorFromStreamBenchmark {
@Benchmark
public int iteratorFromStream(Data data) {
int sum = 0;
Iterator<Integer> iterator = data.list.stream()
.iterator();
while (iterator.hasNext())
sum += iterator.next();
return sum;
}
@Benchmark
public int forEach(Data data) {
int[] sum = {0};
data.list.stream().forEach(integer -> sum[0] = sum[0] + integer);
return sum[0];
}
@State(Scope.Thread)
public static class Data {
private List<Integer> list;
private int size = 100;
@Setup
public void init() {
list = IntStream.range(0, size).boxed().collect(toList());
}
}
}
Which yields:
Benchmark Mode Cnt Score Error Units
forEach avgt 100 133,118 ± 1,580 ns/op
iteratorFromStream avgt 100 228,061 ± 5,491 ns/op
The question here is not only huge difference in absolute values, but the fact 'forEach' now appears to be faster than 'iteratorFromStream'. Also error is lower in case of value returning benchmark.
Could anyone explain is it correct behaviour of Blackhole?
Best regards,
Sergei Tsypanov
More information about the jmh-dev
mailing list