为什么Function.prototype.bind变慢? [英] Why is Function.prototype.bind slow?

查看:123
本文介绍了为什么Function.prototype.bind变慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当比较此基准与Chrome 16与Opera 11.6时,我们发现

$在chrome本地绑定中的b
$ b

  • 几乎比模拟版本的绑定慢5倍在opera本地绑定中,
  • 几乎是4时间快于模拟版本的绑定



在这种情况下,模拟版本的绑定是

  var emulatebind = function(f,context){
return function(){
f.apply(context,arguments);
};
};

有没有很好的理由说明为什么会有这样的差异,或者这只是v8的问题,而不是足够优化?注意: emulatebind 只能实现一个子集,但这并不真正相关。如果您拥有全功能和优化的模拟绑定,那么基准测试中的性能差异仍然存在。 noreferrer> http://jsperf.com/bind-vs-emulate/6 ,它增加了es5-shim版本进行比较,它看起来像罪魁祸首是额外的分支和 instanceof 绑定版本必须执行以测试它是否被称为构造函数。



每次运行绑定版本时,代码执行本质上是:

  if(this instanceof bound){
//永远不会到达,但`instanceof `check and branch大概有
的成本} else {
return target.apply(
that,
args.concat(slice.call(arguments))
) ;

// args是[]在你的情况下。
//所以成本是:
// *将(空)Arguments对象转换为(空)数组。
// *并列两个空数组。
}

在V8源代码中,出现此检查(位于 boundFunction

  if(%_IsConstructCall()){
return%NewObjectFromBound(boundFunction);

明文链接到v8natives.js ,当谷歌代码搜索结束时。)



它有点令人费解,至少对于Chrome 16而言,es5-shim版本仍然比原生版本更快。而其他浏览器对于es5-shim与本机的结果相差很大。推测:可能是%_ IsConstructCall()甚至比这个实例绑定慢,这可能是由于跨越native / JS代码边界。也许其他浏览器可以更快地检查 [[Construct]] 调用。


When comparing this benchmark with chrome 16 vs opera 11.6 we find that

  • in chrome native bind is almost 5 times slower then an emulated version of bind
  • in opera native bind is almost 4 times faster then an emulated version of bind

Where an emulated version of bind in this case is

var emulatebind = function (f, context) {
    return function () {
        f.apply(context, arguments);
    };
};

Are there good reasons why there is such a difference or is this just a matter of v8 not optimizing enough?

Note: that emulatebind only implements a subset but that isn't really relevant. If you have a fully featured and optimised emulated bind the performance difference in the benchmark still exists.

解决方案

Based on http://jsperf.com/bind-vs-emulate/6, which adds the es5-shim version for comparison, it looks like the culprit is the extra branch and instanceof that the bound version has to perform to test if it's being called as a constructor.

Each time the bound version is run, the code that gets executed is essentially:

if (this instanceof bound) {
    // Never reached, but the `instanceof` check and branch presumably has a cost
} else {
    return target.apply(
     that,
     args.concat(slice.call(arguments))
    );

    // args is [] in your case.
    // So the cost is:
    // * Converting (empty) Arguments object to (empty) array.
    // * Concating two empty arrays.
}

In the V8 source code, this check appears (inside boundFunction) as

if (%_IsConstructCall()) {
    return %NewObjectFromBound(boundFunction);
}

(Plaintext link to v8natives.js for when Google Code Search dies.)

It is a bit puzzling that, for Chrome 16 at least, the es5-shim version is still faster than the native version. And that other browsers have rather varying results for es5-shim vs. native. Speculation: maybe %_IsConstructCall() is even slower than this instanceof bound, perhaps due to crossing native/JS code boundaries. And perhaps other browsers have a much faster way of checking for a [[Construct]] call.

这篇关于为什么Function.prototype.bind变慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆