Impact of Intrinsics and inlining on Lambda's

2019-04-28 06:03发布

问题:

I have used this benchmark java8-lambda-performance-test and when running it I have done the followings:

1.Disabled Intrinsic usage

2.Disabled Inlining

3.Disabled Compiling mode

I have found out that disabling the two first optimizations has no effect on results.

Which is strange, and also when running the benchmark with and print intrinsic, I did not find any call to the intrinsic compiledLambdaForm

Since maths intrinsics are heavily used there _min,_pow... I was expecting that disabling intrinsics would have slown the performance

回答1:

The reason why you haven't noticed an expected performance effect is poorly written benchmark.
I rewrote the benchmark using JMH and the things finally got right.

package lambdademo;

import org.openjdk.jmh.annotations.*;

import java.util.List;

@State(Scope.Benchmark)
public class LambdaBenchmark {
    @Param("100")
    private static int loopCount;

    private static double identity(double val) {
        double result = 0;
        for (int i=0; i < loopCount; i++) {
            result += Math.sqrt(Math.abs(Math.pow(val, 2)));    
        }
        return result / loopCount;
    }

    private List<EmployeeRec> employeeList = new EmployeeFile().loadEmployeeList();

    @Benchmark
    public double streamAverage() {
        return streamAverageNoInline();
    }

    @Benchmark
    @Fork(jvmArgs = "-XX:-Inline")
    public double streamAverageNoInline() {
        return employeeList.stream()
                .filter(s -> s.getGender().equals("M"))
                .mapToDouble(s -> s.getAge())
                .average()
                .getAsDouble();
    }

    @Benchmark
    public double streamMath() {
        return streamMathNoIntrinsic();
    }

    @Benchmark
    @Fork(jvmArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:DisableIntrinsic=_dpow,_dabs,_dsqrt"})
    public double streamMathNoIntrinsic() {
        return employeeList.stream()
                .filter(s -> s.getGender().equals("M"))
                .mapToDouble(s -> identity(s.getAge()))
                .average()
                .getAsDouble();
    }
}

Here are the results:

Benchmark                              Mode  Cnt     Score    Error  Units
LambdaBenchmark.streamAverage          avgt    5    71,490 ±  0,770  ms/op
LambdaBenchmark.streamAverageNoInline  avgt    5   122,740 ±  0,576  ms/op
LambdaBenchmark.streamMath             avgt    5    92,672 ±  1,538  ms/op
LambdaBenchmark.streamMathNoIntrinsic  avgt    5  5747,007 ± 20,387  ms/op

As expected, the benchmark with -XX:-Inline works 70% longer, and the version with Math intrinsics disabled appears to be 60 times slower!



回答2:

I don't think that there is any effect of the intrinsics, because Lambda expressions uses mainly the class LambdaMetaFactory.So that is why both inlining and intrinsics has no effect on the lambda itself.

Now for the maths intrinsics my believe is that since they are only used in the identity method,which is only used in the case of LambdaExtraAverage and LambdaExtraSerial tests then they will not affect much the benchmark results.



标签: java lambda jvm