JMH - 为什么JIT不能消除我的死代码

Bye*_*Bye 3 java jit jmh

我写了两个基准来证明JIT可能是编写精细基准测试的问题(请跳过我在这里不使用@State):

@Fork(value = 1)
@Warmup(iterations = 2, time = 10)
@Measurement(iterations = 3, time = 2)
@BenchmarkMode(Mode.AverageTime)
public class DeadCodeTraps {

    @Benchmark
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public static void summaryStatistics_standardDeviationForFourNumbers() {
        final SummaryStatistics summaryStatistics = new SummaryStatistics();
        summaryStatistics.addValue(10.0);
        summaryStatistics.addValue(20.0);
        summaryStatistics.addValue(30.0);
        summaryStatistics.addValue(40.0);
        summaryStatistics.getStandardDeviation();
    }

    @Benchmark
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public static void summaryStatistics_standardDeviationForTenNumbers() {
        final SummaryStatistics summaryStatistics = new SummaryStatistics();
        summaryStatistics.addValue(10.0);
        summaryStatistics.addValue(20.0);
        summaryStatistics.addValue(30.0);
        summaryStatistics.addValue(40.0);
        summaryStatistics.addValue(50.0);
        summaryStatistics.addValue(60.0);
        summaryStatistics.addValue(70.0);
        summaryStatistics.addValue(80.0);
        summaryStatistics.addValue(90.0);
        summaryStatistics.addValue(100.0);
        summaryStatistics.getStandardDeviation();
    }

}
Run Code Online (Sandbox Code Playgroud)

我认为JIT将消除死代码,因此两个方法将同时执行.但最后,我有:

summaryStatistics_standardDeviationForFourNumbers 0.158±0.046 DeadCodeTraps.summaryStatistics_standardDeviationForTenNumbers 0.359±0.294

为什么JIT不优化它?结果summaryStatistics.getStandardDeviation();不会在方法之外的任何地方使用,也不会被它返回.

(我使用的是OpenJDK build 10.0.2 + 13-Ubuntu-1ubuntu0.18.04.4)

rus*_*tyx 6

如果您正在谈论Apache Commons Math SummaryStatistics类,那么它就是一个庞大的类.它的结构肯定不会被内联.要了解原因,请继续使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:-BackgroundCompilation

内联后消除死代码.未使用的对象将反向传播,但非内联构造函数将破坏链,因为JIT优化器不再能确定没有副作用.

换句话说,您希望被淘汰的代码太大了.