为什么Java不在循环中存储条件的值?

时间:2012-08-03 02:49:47

标签: java iteration compiler-optimization

例如:

for(int i = 0; i < 20 * 40 * 60 * 80; i++){ ... }

与:相比:

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

第一个循环比第二个循环慢得多(做了一些时间试验),即使条件的值在整个迭代的任何阶段都不会改变。当然,使用方法会有所不同,因为该值可能会发生变化(即使它可能不应该)。我只是想知道为什么Java不会缓存/临时该值。

long fact10 = factorial(10);
for(long n = 0; n < fact10; n++)    vs   for(long n = 0; n < factorial(10); n++)

5 个答案:

答案 0 :(得分:6)

Java无法进行第二次优化,因为它不知道factorial没有副作用。就第一个基准测试而言,我确信这是某种错误:Java编译器在编译时计算常量表达式的结果,因此前两个循环是等效的。

答案 1 :(得分:2)

我认为你的微基准是有缺陷的,大​​多数是。

正确的基准测试是一种艺术形式。 Oracle JVM有一个即时编译器(JIT),我相信如果你运行这么长时间,你会看到它最终加速,因为他们试图推断这些值永远不会改变。

答案 2 :(得分:0)

理论上(尽管我在这方面取得了不好的成绩),你可以改变你的“&lt;”的结果。循环中的陈述。

例如:

int x = 1;

for(int i = 0; i < x * 2; i++)
{
  if(x < 10)
     x += i;
}

我不知道为什么每次都进行计算的确切原因,无论值如何,但在每次迭代过程中,如果存在变量,它总是重新计算数学。

答案 3 :(得分:0)

我认为没关系,每次都会检查这个条件。所以你可以实现这样的东西:

        synchronized (veryBigList) {
            for (Iterator iter = veryBigList.iterator();iter.hasNext();) {
                Object o = iter.next();
                //Do something
            }
        }

请注意,某些列表实现具有不同的性能。 我想(现在不确定),

ArrayList size()上速度非常快,但在add()上速度很慢 底层阵列必须扩展。 LinkedList size()上很慢, 但在add()

上非常快

我更喜欢这个解决方案:

    synchronized (veryBigList) {
        for (int i = 0, l = veryBigList.size(); i < l; i++) {
            //Do something
        }
    }

答案 4 :(得分:0)

自从我编写了一个小程序以来,你在循环中所拥有的内容在两种情况下所用的时间几乎相同。所以它真的取决于你在第一和第二循环中的内容。

public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        int x = 0;
        for (int i = 0; i < 500000000 ; i++) {
            x++;
        }
        long endTime = System.currentTimeMillis();
        long totalTime1 = endTime - startTime;
        System.out.println("First time " + totalTime1);

        startTime = System.currentTimeMillis();
        int j = 0;
        for (int i = 0; i < 50 * 100 * 10 * 10000 ; i++) {
            j++;
        }
        endTime = System.currentTimeMillis();
        long totalTime2 = endTime - startTime;
        System.out.println("Second time " + totalTime2);


        System.out.println( "First Loop " + totalTime1 + " Second Loop " + totalTime2 );
}