Why do neither V8 nor spidermonkey seem to unroll static loops?(为什么V8和蜘蛛猴似乎都没有展开静态循环?)
问题描述
做一个小检查,看起来V8和蜘蛛猴都没有展开循环,即使很明显,它们有多长(字面上是条件,在本地声明): 数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const f = () => {
let counter = 0;
for (let i = 0; i < 100_000_000; i++) {
counter++;
}
return counter;
};
const g = () => {
let counter = 0;
for (let i = 0; i < 10_000_000; i += 10) {
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
}
return counter;
}
let start = performance.now();
f();
let mid = performance.now();
g();
let end = performance.now();
console.log(
`f took ${(mid - start).toFixed(2)}ms, g took ${(end - mid).toFixed(2)}ms, ` +
`g was ${((mid - start)/(end - mid)).toFixed(2)} times faster.`
);
这有什么原因吗?它们执行的优化要复杂得多。标准的for
循环在Java脚本中是不常见的吗?它不值得吗?
编辑:就像注释一样:有人可能会说,优化可能被延迟了。情况似乎并非如此,尽管我在这方面不是专家。我使用node --allow-natives-syntax --trace-deopt
,手动执行优化,没有观察到取消优化发生(折叠的代码片段,实际上不能在浏览器中运行):
数据-lang="js"数据-隐藏="真"数据-控制台="假"数据-巴贝尔="假">
const { performance } = require('perf_hooks');
const f = () => {
let counter = 0;
for (let i = 0; i < 100_000_000; i++) {
counter++;
}
return counter;
};
// collect metadata and optimize
f(); f();
%OptimizeFunctionOnNextCall(f);
f();
const start = performance.now();
f();
console.log(performance.now() - start);
使用普通版本和展开版本时,效果相同。
推荐答案
(此处为V8开发人员)
TL;DR:因为对于现实世界的代码来说,这几乎不值得。
循环展开与其他增加代码大小(如内联)的优化一样,是一把双刃剑。是的,它是有帮助的;尤其是对于像这里张贴的这样的小玩具例子来说,它经常是有帮助的。但它也会损害性能,最明显的原因是它增加了编译器必须完成的工作量(因此增加了完成该工作所需的时间),但也会产生次要影响,如代码越大,从CPU缓存工作中获益越少。V8的优化编译器实际上喜欢展开循环的第一次迭代。此外,碰巧的是,我们目前有一个正在进行的项目来展开更多的循环;目前的状态是它有时有用,有时有害,所以我们仍然在微调启发式,以确定它何时应该起作用,什么时候不应该起作用。这一困难还表明,对于现实世界的Java脚本,好处通常很小。不管它是不是标准的for
-loop";;理论上任何循环都可以展开。碰巧的情况是,除了微基准测试之外,循环展开往往不会有什么不同:仅仅进行另一次迭代不会产生太多开销,所以如果循环体做的比counter++
更多,那么避免每次迭代的开销不会有太大好处。简而言之,每个迭代的开销不是您的测试测量的:重复的增量全部折叠,所以您在这里真正比较的是counter += 1
的100M次迭代和counter += 10
的10M次迭代。
这是许多误导性微基准的例子之一,这些例子试图欺骗我们得出错误的结论;-)
这篇关于为什么V8和蜘蛛猴似乎都没有展开静态循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么V8和蜘蛛猴似乎都没有展开静态循环?
基础教程推荐
- 响应更改 div 大小保持纵横比 2022-01-01
- 我什么时候应该在导入时使用方括号 2022-01-01
- 在 JS 中获取客户端时区(不是 GMT 偏移量) 2022-01-01
- 在for循环中使用setTimeout 2022-01-01
- Karma-Jasmine:如何正确监视 Modal? 2022-01-01
- 有没有办法使用OpenLayers更改OpenStreetMap中某些要素 2022-09-06
- 悬停时滑动输入并停留几秒钟 2022-01-01
- 动态更新多个选择框 2022-01-01
- 当用户滚动离开时如何暂停 youtube 嵌入 2022-01-01
- 角度Apollo设置WatchQuery结果为可用变量 2022-01-01