【问题标题】:I wrote two pieces of code, almost exactly the same, but one runs much faster than the other (Java)我写了两段代码,几乎一模一样,但一个运行得比另一个快得多(Java)
【发布时间】:2020-04-11 04:16:05
【问题描述】:

我跑了这段代码:(外循环运行100次,内循环运行10亿次。)

long l = 0;

for(int i = 0; i < 100; i++)
    for(int j = 0; j < 1000000000; j++)
        l++;

System.out.println(l);

我运行它大约需要 11-12 秒。

然后我运行了这段代码:

long l = 0;
int i = 0, j = 0;

for(; i < 100; i++)
    for(; j < 1000000000; j++)
        l++;

System.out.println(l);

每当我运行它时,这大约需要 100 毫秒(0.1 秒)。

有人知道为什么会有很大的不同吗?我的理论是,对于 'i' 的每个值,内部 for 循环必须再次初始化 j,这使它有更多的操作要做,所以它需要更长的时间是有道理的。然而,差异是巨大的(大约 100 倍),并且在其他类似的测试中,不会发生同样的事情。

如果你想自己看,我是这样计时的:

class Main {
    static long start, end;
    public static void main(String[] args) {
        start();

        long l = 0;
        int i = 0, j = 0;

        for(; i < 100; i++)
            for(; j < 1000000000; j++)
                l++;

        System.out.println(l);

        end();
        print();
    }

    public static void start() {
        start = System.currentTimeMillis();
    }

    public static void end() {
        end = System.currentTimeMillis();
    }

    public static void print() {
        System.out.println((end -  start) + " ms.");
    }
}

【问题讨论】:

  • 您可以从l 的值检查迭代。第二个函数会少 100 倍。
  • 与您的问题并不真正相关,但由于您正在尝试执行所谓的基准测试,您知道Java Microbenchmarking Harness 吗?

标签: java loops for-loop time


【解决方案1】:

第二个函数仅在 i 的第一次迭代中遍历 j。此时 j 超过了 for 循环的限制并且永远不会再次运行,因为它不会在 i 的下一次迭代中重置

【讨论】:

    【解决方案2】:

    在您的第一个示例中,对于 i 的每个值,内部循环从 0 运行到 1000000000,因为我们正在为 i 的每个值初始化 j=0。
    在您的第二个示例中,内部循环仅在 i = 0 时从 0 运行到 1000000000,因为这里我们仅为外部循环的第一次迭代(即 i = 0)初始化 j = 0。

    【讨论】:

      【解决方案3】:

      真正的原因是在第二种情况下,循环的运行方式与第一种代码不同。

      在第一个代码中,每次你进入你都会开始 j。与 0 但是在第二个代码中,j 在第一次迭代中将是 10 亿。之后它总是 1billoin。这意味着第二个循环条件每次都失败。第二个循环不会运行超过一次。

      【讨论】:

        【解决方案4】:

        这两个版本并不“几乎完全相同”。事实上,它们是完全不同的。

        线索是他们为l打印不同的值:

        /tmp$ java Main1.java
        1000000000
        12 ms.
        
        /tmp$ java Main2.java
        100000000000
        857 ms.
        

        很明显,一个版本的迭代次数是另一个版本的 100 倍。 @Oli's answer 解释了原因。


        我的理论是,对于 i 的每个值,内部 for 循环必须再次初始化 j,这使它有更多的操作要做,所以它需要更长的时间是有道理的。

        不。这并不能解释 100 倍的性能差异。 不合理int 变量的 100 次初始化将花费(在我的机器上)800+ 毫秒。

        真正的解释是您正在比较不可比较的计算。

        【讨论】:

        • 我明白了。这就解释了,谢谢。我不知何故错过了。
        【解决方案5】:

        j 在 for 循环之外设置为 0。在 i 的下一次迭代中,它永远不会重置回 0。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-22
          • 2012-03-03
          • 2020-06-26
          • 1970-01-01
          • 2022-11-25
          • 1970-01-01
          • 2016-01-27
          • 1970-01-01
          相关资源
          最近更新 更多