为什么Function.prototype.bind变慢? [英] Why is Function.prototype.bind slow?
问题描述
当比较此基准与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 $内c $ c $)作为
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屋!