【问题标题】:What's the deal with optimising arguments?优化参数有什么用?
【发布时间】:2015-03-23 05:24:34
【问题描述】:

众所周知,在 JavaScript 中不当使用 arguments 可能会导致函数无法优化(请参阅 herehere by the end):

function notOptimisable (a, b) {
  // Optimising compiler says: Nope.
  var args = [].slice.call(arguments)
}

但是,到目前为止,没有任何消息来源能够解释为什么这会阻止优化发生

这更令人难以置信,因为我所要做的就是

function optimisable (a, b) {
  // Optimising compiler says: I can do this!
  var args = new Array(arguments.length)
    , i = 0

  // Copy the arguments into an actual array, very carefully...
  for(i; i < args.length; ++i)
     args[i] = arguments[i]
}

瞧——我有一个 arguments 的副本,它是一个实际的数组,并且可以优化函数:

node --trace_opt --trace_deopt script.js # Exerpt below

[marking 0x24ba2c0bf0f1 <JS Function notoptimisable (SharedFunctionInfo 0x26b62a724859)> for recompilation, reason: small function, ICs with typeinfo: 3/3 (100%), generic ICs: 0/3 (0%)]
[disabled optimization for 0x26b62a724859 <SharedFunctionInfo notoptimisable>, reason: Bad value context for arguments value]
[failed to optimize notoptimisable: Bad value context for arguments value]
[marking 0x24ba2d0041b1 <JS Function optimisable (SharedFunctionInfo 0x26b62a7247b1)> for recompilation, reason: small function, ICs with typeinfo: 7/7 (100%), generic ICs: 0/7 (0%)]
[optimizing 0x24ba2d0041b1 <JS Function optimisable (SharedFunctionInfo 0x26b62a7247b1)> - took 0.039, 0.164, 0.051 ms]

因此,我问你:

为什么?

  • 哪些技术挑战阻碍了优化?
  • 为什么 v8 引擎不能像第二个代码示例显示的那样简单地返回一个标准的参数数组并优化函数?
  • 另外,为什么 arguments 从语言设计的角度来看只是一个“类似数组”的对象(即它有数字键,但它不是 Array 的后代)并且它是否在某种程度上起到了作用优化过程?

【问题讨论】:

标签: javascript optimization v8


【解决方案1】:

没有不可克服的技术挑战。这只是在 Crankshaft 中实现参数对象期间做出的一个捷径决定:仅支持可以轻松避免参数对象实现的情况。

即使 Crankshaft 支持参数对象的具体化,生成的代码仍然会比不分配参数对象的代码

这只是在 10 分钟内支持最快的案例与在 10 天内支持较慢但更通用的案例的问题。 (10 分钟/10 天是虚数,我只是想表达实现复杂性的规模差异)。

如果想要支持参数对象具体化(并可能泄漏)的情况,则需要考虑参数对象和参数之间的别名 - 这会改变为这些变量构造 SSA 表单的方式。由于类似的原因,这也使内联复杂化。

更通用的参数对象方法应该基于转义分析/分配下沉通道 - 但 Crankshaft 在实施时没有类似的东西,它仍然需要至少支持一些快速路径来处理参数。

【讨论】:

  • 对帮助开发 v8、花时间给出如此长的诚实回复、使用 mac 以及向 chrome 提供这个有用的 --js-flags="--trace-deopt --code-comments" 参数表示赞赏。
【解决方案2】:

arguments 不是数组,例如考虑:

function abc(a) {
    arguments[0] = 1;
    console.log(a);
}
abc(0);

这里的问题是arguments[0] = 1的赋值神奇地改变了a的值,即。 arguments[0]aliasesa。这与evalwith 导致的问题相同——您无法再静态地查看正在更改哪些变量以及何时更改。

strict mode 下,它消除了别名错误功能,没有技术上的理由说明这不会是可优化的,但它可能被认为不值得,因为大多数网络一开始并没有使用严格模式为生产代码放置或删除它。

【讨论】:

  • 那么严格模式呢,那里可以优化吗?
  • @Bergi 实际上应该没有问题,它只是没有为严格模式完成 - 大多数网络都没有使用严格模式
  • 我已经知道它不是一个数组。这个问题真的是关于不同的东西......
  • 我在找。该示例所揭示的只是命名参数变量arguments 中的项目相同。这如何回答 v8 为何无法优化此类功能的问题?
  • @RobertRossmann 真的吗?即使代码从未触及a,您在a 更改其值时也看不到任何奇怪的东西?
【解决方案3】:

原因可能是因为 JavaScript 没有实现传统意义上的实际数组。数组更像 JavaScript 对象,即{},具有长度属性。 arguments 不是 Array 的事实是语言中的设计错误。这可能是优化器出现问题的原因。

【讨论】:

  • 好的,这有助于理解为什么arguments 不是数组,但这对优化有何影响? v8 似乎没有优化对象或数组的问题。
猜你喜欢
  • 2016-10-10
  • 2010-09-29
  • 2016-06-22
  • 2017-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
相关资源
最近更新 更多