为什么 JavaScript 代码在 Node.js 优化后 运行 变慢
Why does this JavaScript code run slower after Node.js optimization
当我 运行 遇到一个有趣的问题时,我正在为 ICPC problem using JavaScript and 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`);
}
这是 运行ning node --trace-opt code.js
使用 Node
v10.15.1:
的输出
[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;
我提交了错误报告并得到了 following response from a Chromium 开发者:
Some array builtins used branch hints for loop bounds checks,
causing all code after the inlined builtin to become deferred
code. This is detrimental for performance.
事实证明这是 TurboFan
编译器和 a fix has been created 的一个已知问题,目前正在测试中:
This CL removes the
hints, which improves code scheduling a lot, on the micro
benchmark from the linked bug by 3x.
当我 运行 遇到一个有趣的问题时,我正在为 ICPC problem using JavaScript and 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`);
}
这是 运行ning node --trace-opt code.js
使用 Node
v10.15.1:
[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;
我提交了错误报告并得到了 following response from a Chromium 开发者:
Some array builtins used branch hints for loop bounds checks, causing all code after the inlined builtin to become deferred code. This is detrimental for performance.
事实证明这是 TurboFan
编译器和 a fix has been created 的一个已知问题,目前正在测试中:
This CL removes the hints, which improves code scheduling a lot, on the micro benchmark from the linked bug by 3x.