JMH - why JIT does not eliminate my dead-code

ByeBye :

I wrote two benchmarks to demonstrate that JIT can be a problem with writing fine benchmark (Please skip that I doesnt use @State here):

@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();
    }

}

I thought that JIT will eliminate dead code, so two methods will be executed at the same time. But in the end, I have:

summaryStatistics_standardDeviationForFourNumbers 0.158 ± 0.046 DeadCodeTraps.summaryStatistics_standardDeviationForTenNumbers 0.359 ± 0.294

Why JIT does not optimize it? The result of summaryStatistics.getStandardDeviation(); is not used anywhere outside the method and it is not returned by it.

(I am using OpenJDK build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)

rustyx :

If you're talking about the Apache Commons Math SummaryStatistics class, then it's a massive class. Its construction will most certainly not be inlined. To see why, run with -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:-BackgroundCompilation

Dead code elimination happens after inlining. Unused objects will back-propagate, but the non-inlined constructor will break the chain because the JIT optimizer can no longer be sure there are no side effects.

In other words, the code you expect to be eliminated is too big.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=88334&siteId=1