JMH-为什么JIT无法消除我的无效代码

时间:2019-01-14 15:58:57

标签: 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();
    }

}

我认为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)

1 个答案:

答案 0 :(得分:6)

如果您要谈论的是Apache Commons Math SummaryStatistics类,那么这是一个庞大的类。它的构造肯定不会被内联。要了解原因,请运行-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:-BackgroundCompilation

内联后会消除死代码。 未使用的对象将向后传播,但是非内联的构造函数将打破此链,因为JIT优化器无法再确保没有副作用。

换句话说,您希望消除的代码太大。