用于优化循环语句的 JVM 选项 [英] JVM option to optimize loop statements

查看:23
本文介绍了用于优化循环语句的 JVM 选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在学校被告知修改 for 循环 的索引变量是一种不好的做法:

I've been told at school that it's a bad practice to modify the index variable of a for loop:

示例:

for(int i = 0 ; i < limit ; i++){
    if(something){
        i+=2;      //bad
    }
    if(something){
        limit+=2;      //bad
    }
}

争论是一些编译器优化可以优化循环,而不是在每个循环中重新计算索引和边界.

The argument was that some compiler optimization can optimize the loop and not recalculate the index and bound at each loop.

我在 java 中做了一些测试,似乎默认情况下每次都会重新计算索引和边界.

I 've made some test in java and it seems that by default index and bound are recalculate each time.

我想知道是否可以在 JVM HotSpot 中激活这种功能?

例如优化这种循环:

for(int i = 0 ; i < foo.getLength() ; i++){   }

无需写:

int length = foo.getLength()
for(int i = 0 ; i < length ; i++){   }

这只是一个例子,我很想尝试看看改进.

It's just an example I'm curious to try and see the improvments.

编辑

根据 Peter Lawrey 的回答 为什么在这个简单的例子中 JVM 不内联 getLength() 方法?:

According to Peter Lawrey answer why in this simple example the JVM don't inline getLength() method? :

public static void main(String[] args) {
   Too t = new Too();
   for(int j=0; j<t.getLength();j++){
   }
}


class Too {

    int l = 10;
    public Too() {
    }
    public int getLength(){
        //System.out.println("test");
        return l;
    }
}

在输出test"中打印 10 次.

In the output "test" is print 10 times.

我认为优化这种执行方式会很好.

I think it could be nice to optimize this kind of execution.

编辑 2:好像误会了...

我已经删除了 println 并且实际上探查器告诉我方法 getLength() 在这种情况下甚至没有调用一次.

I have remove the println and indeed the profiler tell me that the method getLength() is not even call once in this case.

推荐答案

我在java中做了一些测试,似乎默认情况下每次都会重新计算索引和边界.

I've made some test in java and it seems that by default index and bound are recalculate each time.

根据 Java 语言规范,这是:

According to the Java Language Specification, this:

for(int i = 0 ; i < foo.getLength() ; i++){   }

表示在每次循环迭代中调用 getLength().Java 编译器仅允许getLength() 调用移出循环,前提是它们可以有效地证明它不会改变可观察的行为.

means that getLength() is called on each loop iteration. Java compilers are only allowed to move the getLength() call out of the loop if they can effectively prove that it does not alter the observable behavior.

(例如,如果 getLength() 只是返回某个变量的值,那么 JIT 编译器就有可能内联调用.如果 内联后它可以推断变量不会改变(在某些假设下)它可以应用提升优化.另一方面,如果 getLength() 涉及获取并发或同步集合的长度,则提升优化被允许的可能性很小甚至没有......因为其他线程的潜在操作.)

(For instance, if getLength() just returns the value of some variable, then there is a chance that the JIT compiler can inline the call. If after inlining it can deduce that the variable won't change (under certain assumptions) it can apply a hoisting optimization. On the other hand, if getLength() involves getting the length of a concurrent or synchronized collection, the chances are slim to none that the hoisting optimization will be permitted ... because of potential actions of other threads.)

这就是编译器允许做的事情.

So that's what a compiler is allowed to do.

我想知道是否可以在 JVM HotSpot 中激活这种功能?

I'm wondering if it's possible to activate this kind of feature in the JVM HotSpot?

简单的答案是否定的.

您似乎建议使用编译器开关来告诉/允许编译器忽略 JLS 规则.没有这样的开关.这样的转换将是一个糟糕的想法.它可能会导致正确/有效/工作程序中断.考虑一下:

You seem to be suggesting a compiler switch that tells / allows the compiler to ignore the JLS rules. There is no such switch. Such a switch would be a BAD IDEA. It would be liable to cause correct/valid/working programs to break. Consider this:

class Test {
   int count;

   int test(String[] arg) {
       for (int i = 0; i < getLength(arg); i++) {
           // ...
       }
       return count;
   }

   int getLength(String[] arg) {
       count++;
       return arg.length;
   }
}

如果允许编译器将 getLength(arg) 调用移出循环,它将改变调用该方法的次数,从而改变 getLength(arg) 返回的值代码>测试方法.

If the compiler was permitted to move the getLength(arg) call out of the loop, it would change the number of times that the method was called, and therefore change the value returned by the test method.

改变正确编写的 Java 程序行为的 Java 优化不是有效的优化.(请注意,多线程往往会搅浑水.JLS,特别是内存模型规则,允许编译器执行优化,这可能导致不同线程看到应用程序状态的不一致版本……如果它们不同步正确,导致从开发人员的角度来看不正确的行为.但真正的问题在于应用程序,而不是编译器.)

顺便说一句,您不应该更改循环体中的循环变量的一个更有说服力的原因是它会使您的代码更难理解.

By the way, a more convincing reason that you shouldn't change the loop variable in the loop body is that it makes your code harder to understand.

这篇关于用于优化循环语句的 JVM 选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆