javascript循环(for语句)在21亿次迭代后变慢?

javascript loop (for statement) slows down after 2.1 billion iteration?

我试图对 javascript 和 .net 核心进行基准测试,以便选择一个服务器端框架来提供一些需要迭代大型数组的特定 restful 服务(约21亿)。在处理一个简单的代码时,我意识到节点在特定的数字迭代后有奇怪的行为。我在多个平台上重复并达到相同的结果。经过测试的平台是:

running video shows surprisingly increase process time about two times from 300ms to 600ms

示例代码:

1。节点:

var cnt = 0;
var logPeriod=100000000;
var max=10000000000;
for (let i = 0; i < max; i++) {
  if (i % logPeriod === 0) {
    // var end = Date.now();
    if (i !== 0) {
      console.timeEnd(cnt*logPeriod, i);
      cnt++;
    }
    console.time(cnt*logPeriod);
  }
}

2.browser

<!DOCTYPE html>
<html>
  <head>
    <script>
      function doloop() {
        var cnt = 0;
        var logPeriod = 100000000;
        var max = 10000000000;
        for (let i = 0; i < max; i++) {
          if (i % logPeriod === 0) {
            // var end = Date.now();
            if (i !== 0) {
              console.timeEnd(cnt * logPeriod, i);
              cnt++;
            }
            console.time(cnt * logPeriod);
          }
        }
      }
    </script>
  </head>
  <body>
    <button onclick="doloop()">doloop</button>
  </body>
</html>

这里是 V8 开发人员。

V8 的优化编译器生成的代码尽可能使用纯 32 位整数作为数字。一旦一个数字超过 int32 范围(或精度要求,即当它需要保存小数值时),那么这种优化代码将被丢弃(或者一开始就不会生成)并使用 64 位双精度数代替,因为 JavaScript 规格要求。算术运算(甚至像 i++ 这样简单的运算)在 64 位双精度数上比在 32 位整数上慢,这正是硬件所做的。

就行为而言,这种内部差异是不可观察的:数字总是表现得就好像它们是 64 位双精度数。但这并不意味着引擎实际上总是在引擎盖下使用 64 位双精度数:正如您在此处看到的那样,当引擎可以在内部使用 32 位整数时,会有显着的性能优势。

choose [JavaScript or .net for] restful services which needed to iterate large arrays(about 2.1 billion)

这是一个简单的决定:使用 .net。 V8(以及 Node)不允许您创建包含 21 亿个元素的数组,因为 per-object 大小限制远低于此。当然,var a = new Array(2_100_000_000) 会很好地评估,但那是因为它实际上并没有分配所有的内存。开始填充元素并观察它在一段时间后崩溃:-)

如果您的实际阵列毕竟不会那么大,那么请定义一个更接近您实际工作负载的基准,因为它的结果将更具代表性,因此对您的 decision-making 更有用。