【问题标题】:Why does for(var i = 0; i < 600000000000; i++) {} runs so long in JavaScript为什么 for(var i = 0; i < 600000000000; i++) {} 在 JavaScript 中运行这么长时间
【发布时间】:2014-12-05 12:00:50
【问题描述】:

我时不时地使用 JS 来解决 Project Euler 上的任务。对于其中一项任务,我必须迭代大约 6000 亿个连续数字。令我惊讶的是,在 NodeJS 中花了大约 14 个小时。

只需运行下面的 sn-p,您的浏览器就会卡住几个小时(我尝试过 Chrome 和 Firefox):

console.time('t')
for (var i = 0; i < 600851475143; i++) {}
console.timeEnd('t')

作为比较,在 Java 中它在我的机器上运行大约 200 毫秒,如果我计算每个 i 的平方根,则需要 4 秒。

发生了什么???

更新: 我知道迭代每个数字并不是解决这个特殊的 PE 问题的正确方法。问题不在于那个。

更新 2: 我误解了Java。正如人们正确指出的那样,它只是物理上无法运行得这么快。我只是用错了号码,对不起。

【问题讨论】:

  • JVM 很可能完全消除了整个for 语句,因为它不会产生任何副作用。而且 V8 还没有那么智能(还)
  • @zerkms 仔细阅读:如果我在每次迭代中计算当前 i 的平方根,JVM 运行 4 秒。
  • 仔细制作您的示例 - 在您的示例中这是一个空的主体循环。
  • @GeorgiyIvankin 实际上是什么任务?
  • @Georgiy Ivankin:“为什么在 JVM 上计算直到这个数字的每个平方根都需要 4 秒?” --- JVM 是令人难以置信的复杂玩具。它可能会将您的循环扩展为单个或多个表达式,或进行其他优化。如果它“不是立即”运行,并不意味着它执行了 600851475143 次操作。

标签: javascript performance for-loop v8 gecko


【解决方案1】:

首先,200 毫秒和 4 秒都是完全荒谬的,因为您的处理器很可能每秒最多只能执行 40 亿个周期 (4 GHz),即使一个循环迭代花费 1 个周期,它仍然需要至少 150 秒.然而,即使是一个空循环,每次迭代也会花费至少 3 个周期(假设它没有被优化),计算平方根每次迭代会增加 5-10,所以你根本没有在 4 秒内完成 6000 亿平方根。

而且我什至无法重现,以下内容需要永远按预期运行:

class Test {
    public static void main(String[] args) {
        for (long i = 0; i < 600851475143L; ++i) {
        }
    }
}

然后

$ java -version
java version "1.7.0_55"
OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
$ javac test.java
$ java -cp . Test

【讨论】:

  • 我实际上会要求 OP 为他们的即时版本和 4 秒版本提供字节码,因为这确实很奇怪。
  • 我对 Java 有误解(请参阅问题更新)。所以事实证明,在 4GHz 处理器上,循环运行 6 万亿次,每次迭代需要 10 个处理器周期,大约需要 15000 秒,略多于 4 小时。考虑到我在较慢的处理器上运行代码,现在一切看起来都很清楚。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-10-16
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 2023-03-17
  • 2011-06-14
  • 1970-01-01
相关资源
最近更新 更多