JVM是否能够进行简单的递归调用预计算?

问题描述 投票:1回答:2

前一段时间,我对两种不同的软件乘法算法进行了生锈的基准测试:琐碎的递归乘法和俄罗斯农民乘法。

令我惊讶的是,编译器能够分析平凡的递归,直接用结果替换对方法的调用(例如,调用mul0(4,8) -> 32。]

为了查看JVM是否能够执行相同的优化,我通过JMH测量了以下Java实现。但是,俄罗斯的农民算法速度更快,而且看来VM并没有执行任何类似的优化。

是否在JVM中内置了类似的优化技术(将递归调用替换为预先计算的结果),或者这是JVM出于某种原因本身不执行的操作?

[我知道这取决于VM,并且可能会发生变化,所以我对阻碍VM实现者将此类优化纳入其VM的一般障碍更加感兴趣。

代码段:

@Warmup(iterations = 10)
@Fork(value = 2)
@State(Scope.Benchmark)
public class MyBenchmark {

    private int F1 = 542;
    private int F2 = 323;

    public final static int mul0(int a, int b) {
        if (a == 1) {
            return b;
        }
        return mul0(a - 1, b) + b;
    }

    //O(log n)
    public final static int mul2(int a, int b) {
        if (a == 1) {
            return b;
        }

        int sum = ((a & 1) == 1) ? b : 0;

        return mul2(a / 2, b + b) + sum;
    }

    @Benchmark
    public void test0() {
        mul0(F1, F2);
    }

    @Benchmark
    public void test2() {
        mul2(F1, F2);
    }

}

结果:

Result: 13852692,903 ▒(99.9%) 532102,125 ops/s [Average]
  Statistics: (min, avg, max) = (9899651,068, 13852692,903, 15356453,576), stdev = 945811,061
  Confidence interval (99.9%): [13320590,778, 14384795,028]


# Run complete. Total time: 00:02:22

Benchmark                   Mode  Samples         Score  Score error  Units
d.s.m.MyBenchmark.test0    thrpt       40   1453817,627    68528,256  ops/s
d.s.m.MyBenchmark.test2    thrpt       40  13852692,903   532102,125  ops/s
java performance jvm microbenchmark
2个回答
3
投票

简短回答


2
投票

让我们分析优化对JVM的意义。

© www.soinside.com 2019 - 2024. All rights reserved.