Ray*_*nos 32 javascript google-chrome v8
将此基准与chrome 16与opera 11.6 进行比较时,我们发现了这一点
在这种情况下,绑定的模拟版本是
var emulatebind = function (f, context) {
return function () {
f.apply(context, arguments);
};
};
Run Code Online (Sandbox Code Playgroud)
有没有充分的理由说明为什么存在这样的差异,或者仅仅是v8没有足够优化的问题?
注意:emulatebind这只实现了一个子集,但实际上并不相关.如果您拥有功能齐全且经过优化的模拟绑定,则基准测试中的性能差异仍然存在.
Dom*_*nic 27
基于http://jsperf.com/bind-vs-emulate/6,它添加了es5-shim版本进行比较,看起来罪魁祸首是额外的分支instanceof,并且绑定版本必须执行以测试它是否正在称为构造函数.
每次运行绑定版本时,执行的代码基本上是:
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.
}
Run Code Online (Sandbox Code Playgroud)
在V8源代码中,此检查显示(内部boundFunction)为
if (%_IsConstructCall()) {
return %NewObjectFromBound(boundFunction);
}
Run Code Online (Sandbox Code Playgroud)
(当Google Code Search死亡时,明文链接到v8natives.js.)
令人费解的是,至少对于Chrome 16来说,es5-shim版本仍然比原生版本更快.并且其他浏览器对于es5-shim与native相比具有相当不同的结果.推测:可能%_IsConstructCall()比甚至更慢this instanceof bound,可能是由于跨越本机/ JS代码边界.也许其他浏览器可以更快地检查[[Construct]]呼叫.
bind仅在ES5中实现全功能是不可能的.特别是规范15.3.4.5.1至15.3.4.5.3的部分无法模拟.
特别是15.3.4.5.1似乎是一种可能的性能负担:简而言之,绑定函数具有不同的 [[Call]]内部属性,因此调用它们可能会占用一个不寻常的,可能更复杂的代码路径.
绑定函数的各种其他特定的不可模拟特性(例如arguments/ caller中毒,可能是length独立于原始签名的自定义)可能会增加每次调用的开销,尽管我承认它有点不太可能.虽然看起来V8目前还没有实施中毒.
编辑这个答案是猜测,但我的另一个答案有更接近的证据.我仍然认为这是一个有效的推测,但它是一个单独的答案,所以我会保留它,只是引用你到另一个.
| 归档时间: |
|
| 查看次数: |
4788 次 |
| 最近记录: |