为什么在Node.js优化后此JavaScript代码运行速度较慢

时间:2019-02-27 15:19:53

标签: javascript node.js performance optimization v8

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

我将其剥离下来,直到得到一个演示行为的最小示例:

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 --trace-opt code.js v10.15.1运行Node的输出:

[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

在前三次迭代中,运行时间约为80ms,但在第四次迭代Node之前重新编译并优化了一种方法,从那时起,代码的运行速度慢了约三倍

通常,Node进行运行时分析,重新编译和优化时,所有内容都会运行得更快。

有人能解释为什么Node优化在这种情况下会使情况变得更糟吗?


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

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

1 个答案:

答案 0 :(得分:1)

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

  

某些内置数组使用分支提示进行循环范围检查,   导致内联内置函数被延迟后的所有代码   码。这对性能有害。

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

  

此CL删除了   提示,可以极大地改善代码调度   链接错误的基准测试提高了3倍。