为什么V8和蜘蛛猴似乎都没有展开静态循环?

Why do neither V8 nor spidermonkey seem to unroll static loops?(为什么V8和蜘蛛猴似乎都没有展开静态循环?)
本文介绍了为什么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和蜘蛛猴似乎都没有展开静态循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)