未使用的变量是否真的会影响JIT优化?

时间:2017-03-22 09:34:35

标签: jvm jvm-hotspot

以下是[Java performance]的一个例子:

public  static void main(String[] args){
        double d;
        long start=System.currentTimeMillis();

        for (int i=0;i<10;i++){
            d=fblImpl1(50);
        }
        long end=System.currentTimeMillis();
        System.out.println("elapsed time :"+(end-start));
    }

    private static double fblImpl1(int n){
        if(n<0) throw new IllegalArgumentException("Must be >0");
        if (n==0) return 0d;
        if (n==1) return 1d;
        double d =fblImpl1(n-2) +fblImpl1(n-1);
        if (Double.isInfinite(d)) throw new ArithmeticException("overflow");
        return d;
    }

作者说现代JIT会像这样优化代码:

  long start=System.currentTimeMillis();
  long end=System.currentTimeMillis();
  System.out.println("elapsed time :"+(end-start));

因为程序没有使用变量&#34; d&#34;在下面的。 但是在我的测试中,oracle hostspot jdk1.7没有做这个优化,程序需要运行很长时间才能完成。

@Holger,首先感谢您的回复。根据我的理解,我修改了以下代码:

public static void main(String[] args) {
    for (int i = 0; i < 10000; i++) {
        doTest();
    }
}

private static void doTest() {
    double d;
    long start = System.currentTimeMillis();

    for (int i = 0; i < 10000; i++) {
        d = fblImpl1(50);
    }
    long end = System.currentTimeMillis();
    System.out.println("elapsed time :" + (end - start));
}

private static double fblImpl1(int n) {
    //if (n < 0) throw new IllegalArgumentException("Must be >0");
    if (n == 0) return 0d;
    if (n == 1) return 1d;
    double d = fblImpl1(n - 2) + fblImpl1(n - 1);
    //if (Double.isInfinite(d)) throw new ArithmeticException("overflow");
    return d;
}

} 但似乎JIT仍然没有按照我的预期应用任何优化。有什么不对吗?

1 个答案:

答案 0 :(得分:1)

您不需要多次执行main方法,因为JIT可以编译经常执行的循环,因此不需要“doTest”。方法。似乎问题在于递归。如果用一些像sum这样的小事来替换fblImpl1,那么很容易得到想要的效果。

public static void main(String[] args) {
    double d;
    List<Long> list = new ArrayList<>();
    for (int i = 0; i < 50000; i++) {
        long start = System.nanoTime();
        fblImpl1(20000);
        long end = System.nanoTime();
        list.add(end - start);
    }
    for(long z : list) {
        System.out.println(z);
    }
}

public static double fblImpl1(int n) {
    int sum = 0;
    for(int i = 0; i < n; i++) {
        sum += i;
    }
    return sum;
}

以下代码生成如下结果:首先执行代码,然后获得零。 5812 5811 5812 5812 5812 5812 6088 6089 5812 6089 5812 5812 5811 5812 6089 6088 5812 .... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 277 0 0 0 0 0 0 0 0

我使用以下标志执行代码:

-XX:+PrintCompilation -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining

提示:不要使用SystemCurrentTimeMillis,因为它的精度非常差(特别是在Windows上)