4

例如:

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++)
4

5 回答 5

6

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

于 2012-08-03T02:55:07.260 回答
2

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

正确进行基准测试是一种艺术形式。Oracle JVM 有一个即时编译器 (JIT),我敢肯定,如果你运行了足够长的时间,你会发现它最终会在它启发式地决定这些值永远不会改变后加速。

于 2012-08-03T02:57:32.267 回答
0

从理论上讲(尽管我在这方面取得了不好的成功),您可以在循环中更改“<”语句的结果。

例如:

int x = 1;

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

我不知道它每次都进行计算而不管值的确切原因,但它总是在每次迭代期间重新计算数学,以防出现变量。

于 2012-08-03T02:52:32.450 回答
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
        }
    }
于 2012-08-03T06:28:47.197 回答
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 );
}
于 2012-08-03T14:43:30.487 回答