Java &引用;“回路无开关”;优化不起作用
我听说Java支持“循环取消切换”,所以我只是在JMH中测试了它 我以为JIT之后他们会完全一样。为什么会这样Java &引用;“回路无开关”;优化不起作用,java,performance,jit,Java,Performance,Jit,我听说Java支持“循环取消切换”,所以我只是在JMH中测试了它 我以为JIT之后他们会完全一样。为什么会这样 private final int TIMES = 1_000_000; private boolean bool; private Random r = new Random(93); @Setup(Level.Invocation) public void fresh() { bool = r.nextBoolean(); } @Benchmark public voi
private final int TIMES = 1_000_000;
private boolean bool;
private Random r = new Random(93);
@Setup(Level.Invocation)
public void fresh() {
bool = r.nextBoolean();
}
@Benchmark
public void test1(Blackhole bh) {
for (int i = 0; i < TIMES; i++) {
if (bool) {
bh.consume(1);
} else {
bh.consume(2);
}
}
}
@Benchmark
public void test2(Blackhole bh) {
if (bool) {
for (int i = 0; i < TIMES; i++) {
bh.consume(1);
}
} else {
for (int i = 0; i < TIMES; i++) {
bh.consume(2);
}
}
}
测试环境
#JMH版本:1.21
#虚拟机版本:JDK 1.8.0_222,OpenJDK 64位服务器虚拟机,25.222-b10
JMH禁用黑洞的内联。使用方法。非内联方法是JVM的黑盒-编译器不知道这种方法是否修改字段、抛出异常、注册它的垃圾等。JIT编译器无法在这种方法调用中应用许多优化。(假设一个黑盒方法使用反射来修改bool
字段,因此循环取消切换将变得无效)
当编译范围包括整个循环体时,HotSpot JVM仍然支持循环取消切换,并且已知条件在整个循环中是恒定的
以修改后的基准为例:
@State(Scope.Benchmark)
public class LoopUnswitching {
private static final int TIMES = 10_000;
private final Random r = new Random(93);
private final int[] x = r.ints(TIMES).toArray();
private final int[] y = r.ints(TIMES).toArray();
private boolean bool;
@Setup(Level.Invocation)
public void setup() {
bool = r.nextBoolean();
}
@Benchmark
public int test1() {
int sum = 0;
for (int i = 0; i < TIMES; i++) {
if (bool) {
sum += x[i];
} else {
sum += y[i];
}
}
return sum;
}
@Benchmark
public int test2() {
int sum = 0;
if (bool) {
for (int i = 0; i < TIMES; i++) {
sum += x[i];
}
} else {
for (int i = 0; i < TIMES; i++) {
sum += y[i];
}
}
return sum;
}
}
Benchmark Mode Cnt Score Error Units
LoopUnswitching.test1 avgt 10 2910,432 ± 3,287 ns/op
LoopUnswitching.test2 avgt 10 2912,922 ± 9,367 ns/op