Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jvm 未使用的变量真的会影响JIT优化吗?_Jvm_Jvm Hotspot - Fatal编程技术网

Jvm 未使用的变量真的会影响JIT优化吗?

Jvm 未使用的变量真的会影响JIT优化吗?,jvm,jvm-hotspot,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

下面是[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;
    }
因为程序不使用下面的变量“d”。 但是在我的测试中,OracleHostSpotJDK1.7没有进行这种优化,程序需要运行很长时间才能完成

@霍尔格,首先谢谢你的回复。根据我对你的话的理解,我修改了代码如下:

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;
}
publicstaticvoidmain(字符串[]args){
对于(int i=0;i<10000;i++){
doTest();
}
}
私有静态void doTest(){
双d;
长启动=System.currentTimeMillis();
对于(int i=0;i<10000;i++){
d=fblImpl1(50);
}
long end=System.currentTimeMillis();
System.out.println(“运行时间:+(结束-开始));
}
专用静态双fblImpl1(整数n){
//如果(n<0)抛出新的IllegalArgumentException(“必须大于0”);
如果(n==0)返回0d;
如果(n==1)返回1d;
双d=fblImpl1(n-2)+fblImpl1(n-1);
//if(Double.isInfinite(d))抛出新的算术异常(“溢出”);
返回d;
}
}
但JIT似乎仍然没有像我预期的那样应用任何优化。有什么问题吗?

您不需要多次执行main方法,因为JIT可以编译经常执行的循环,所以不需要“doTest”方法。问题似乎出在递归中。如果将fblImpl1替换为sum之类的琐碎内容,则很容易获得所需的效果

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;
}

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

因为代码可能会抛出异常,JIT必须证明
n
永远不会是负的,
d
永远不会是无限的。除此之外,只有当
main
方法本身被频繁调用时,这种优化才能被预期。否则,很可能优化器的范围太窄,无法完全省略优化。如果它不看
main
方法,而只看递归的
fblImpl1
调用,它就不会意识到您在用相同的输入重复调用它。@Holger,我没有测量doTest的所有循环,但它确实花了很多时间。将循环放在main方法中意味着依赖于堆栈替换。如果有效,很好,但如果无效,则无法证明缺少优化表示总体不可用,因为OSR也可能失败。因此,当优化没有发生时,总是值得尝试使用称为多次的单独方法。虽然递归是问题所在,但测试并不能证明死代码消除已经发生。优化器可以将循环转化为一次乘法,这将产生相同的效果。@Holger你说得对。因此,证明代码被删除的唯一方法似乎是查看汇编代码内部,对吗?除非您找到优化器绝对不能缩短的操作,是的,这是唯一的方法。
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;
}
-XX:+PrintCompilation -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining