我写了两个基准测试来展示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编译版本10.0.2+13-Ubuntu-1ubuntu0.18.04.4)
summaryStatistics.getStandardDeviation();
在方法范围之外没有被使用或返回,因此在JIT优化后保留该代码是没有意义的。或者说它可能会保留该代码,因为无法确定该代码是否具有任何副作用。 - ByeBye