根据 JLS,对于数组,“增强的 for 循环语句等同于基本的 for 循环语句形式”。然而,如果我检查 JDK8 生成的字节码,两种变体都会生成不同的字节码。令人惊讶的是,如果我尝试测量性能,在 jdk8 上增强型的表现似乎更好... 有人能解释为什么吗?我猜这是因为 jmh 测试不正确,如果是这样,请建议如何修复。(我知道 JMH 声明不要使用循环进行测试,但我认为这里不适用,因为我实际上正在尝试测量循环)
我的 JMH 测试相当简单(可能太简单了),但我无法解释结果。以下是测试 JMH 代码,典型结果为:
JdkBenchmarks.enhanced avgt 5 2556.281 ± 31.789 ns/op
JdkBenchmarks.indexed avgt 5 4032.164 ± 100.121 ns/op
意味着通常增强的循环比索引循环更快,它的测量结果也更准确,因此我们无法将差异归因于测量误差。对于使用随机整数初始化的数组或更大的数组,基本上得出相同的结果。
public class JdkBenchmarks {
@Benchmark
@BenchmarkMode(AverageTime)
@OutputTimeUnit(NANOSECONDS)
public void indexed(Blackhole blackhole, TestState testState) {
int length = testState.values.length;
for(int i = 0; i < length; i++) {
blackhole.consume(testState.values[i]);
}
}
@Benchmark
@BenchmarkMode(AverageTime)
@OutputTimeUnit(NANOSECONDS)
public void enhanced(Blackhole blackhole, TestState testState) {
for (int value : testState.values) {
blackhole.consume(value);
}
}
@State(Scope.Benchmark)
public static class TestState {
public int[] values;
@Setup
public void setupArray() {
int count = 1000;
values = new int[count];
for(int i = 0; i < count; i++) {
values[i] = i;
}
}
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JdkBenchmarks.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
int[] array = testState.values;
并使用该本地变量,而不是每次迭代访问testState
变量(就像已经使用length
一样)。 - user16320675@user16320675
是正确的,这就是问题所在。 - Martin Mucha