【问题标题】:Why does this JavaScript code run slower after Node.js optimization为什么这个 JavaScript 代码在 Node.js 优化后运行速度变慢了
【发布时间】:2019-07-21 08:51:44
【问题描述】:

当我遇到一个有趣的问题时,我正在使用 JavaScript 和 Node.js 创建一个 ICPC 问题的解决方案:在某些情况下,我的程序在同一数据集上运行速度会慢两倍。

我对其进行了精简,直到找到了演示该行为的最小示例:

function solve(arr) {
  const total = arr.reduce((a, c) => a + c, 0);
  const count = arr.length;
  for (let i = 0; i < total; i++) {
    for (let j = 0; j < count; j++) {
      // calculate some stuff
    }
  }
}

for (let i = 0; i < 10; i++) {
  // generate some sample data (array of 5000 random numbers 1-10)
  const data = [];
  for (let i = 0; i < 5000; i++) {
    data.push(Math.floor(Math.random() * 10) + 1);
  }

  const start = new Date();
  solve(data);  // run solve on the data
  console.log(`${i + 1}: ${new Date() - start}ms`);
}

这是使用Node v10.15.1 运行node --trace-opt code.js 的输出:

[marking 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> for optimized recompilation, reason: small function, ICs with typeinfo: 5/7 (71%), generic ICs: 0/7 (0%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan OSR]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 1.453, 0.702, 0.082 ms]
1: 86ms
[marking 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> for optimized recompilation, reason: hot and stable, ICs with typeinfo: 22/23 (95%), generic ICs: 1/23 (4%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 0.159, 0.632, 0.096 ms]
2: 82ms
3: 80ms
[compiling method 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> using TurboFan OSR]
[optimizing 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> - took 0.592, 2.312, 0.154 ms]
4: 245ms
5: 243ms
6: 236ms
7: 237ms
8: 240ms
9: 246ms
10: 239ms

在前三个迭代期间,运行时间约为 80 毫秒,但就在第四次迭代之前Node 重新编译并优化了一个方法,从那时起代码运行速度慢了大约 3 倍

通常当Node 进行运行时分析、重新编译和优化时,一切都会运行得更快。

谁能解释为什么Node 优化在这种情况下会让事情变得更糟?


请注意,如果将示例代码更改为通过迭代而不是使用 reduce 来计算 total,则优化会按预期提高性能(运行时间降至 60 毫秒左右):

let total = 0;
for (let v of arr) total += v;

【问题讨论】:

  • 其他部分呢?也许这 240 毫秒和其他一些优化的部分总体上运行得更快?也许其他并行作业变得更快,所以 240 毫秒被摊销了?
  • 我认为您应该将此报告为错误,这肯定是出乎意料的。
  • @Bergi 好点,没有意识到Math.random() 排除了1,代码示例已更新。好主意,我会打开一个问题。
  • 如果您确实提交了错误报告,可以链接吗?
  • @Bergi Node 问题26341V8 问题8922。看起来它是由 V8 中的一个已知编译器问题引起的,目前正在测试修复。

标签: javascript node.js performance optimization v8


【解决方案1】:

我提交了一份错误报告并从Chromium 开发人员那里获得了following response

一些内置数组使用分支提示进行循环边界检查, 导致内联内置函数之后的所有代码都被延迟 代码。这对性能不利。

所以事实证明这是TurboFan 编译器和a fix has been created 的一个已知问题,目前正在测试中:

此 CL 删除 在微上大大改进了代码调度的提示 比链接的错误基准高 3 倍。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2017-11-04
    • 2020-01-18
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 2014-08-31
    相关资源
    最近更新 更多