Java &引用;“回路无开关”;优化不起作用

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

我听说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 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