v8 delete操作存在的这个问题
测试地址在这里,http://jsperf.com/test-v8-delete,也可以用下面的代码在node中测试
var begin = new Date();
function Foo() {}
Foo.prototype.x = 1;
Foo.prototype.y = 2;
//delete Foo.prototype.y;
var foo = new Foo();
var result = 0;
for (var i = 0; i < 100000000; i++) {
result = result + foo.x;
}
var end = new Date();
console.log(end - begin);
需要profile下看看具体情况
delete 操作看来是会有性能问题
这个是因为delete要返回一个Boolean值(true or false). 直接Foo.prototype.y = null;速度会更快.
嗯,意思是delete尽量不要用,delete形同虚设
delete 会引起GC嘛。
可以使用下面的接口来计算时间,不用Date:
console.time(‘deleteTime’); … … console.timeEnd(‘deleteTime’);//打印出执行时间.
待研究!
我增加了property delete的对比测试,比起prototype的性能,property的delete差异不会太大。 prototype delete 差20倍,太夸张了。。。
我的测试结果:
$ node test-v8-delete.js
prototypeDeleteBenchmark:
delete: false, loop: 1000000, usetime: 8 ms
delete: true, loop: 1000000, usetime: 147 ms
propertyDeleteBenchmark:
delete: false, loop: 1000000, usetime: 4 ms
delete: true, loop: 1000000, usetime: 11 ms
我的测试脚本: test-v8-delete.js
function prototypeDeleteBenchmark(number, isDelete) {
function Foo() {}
Foo.prototype.x = 1;
Foo.prototype.y = 2;
if (isDelete) {
delete Foo.prototype.y;
}
var foo = new Foo();
var begin = new Date();
var result = 0;
for (var i = 0; i < number; i++) {
result = result + foo.x;
}
var end = new Date();
console.log('delete: %s, loop: %s, usetime: %d ms', isDelete, number, end - begin);
}
function propertyDeleteBenchmark(number, isDelete) {
var foo = {
x: 1,
y: 2
};
if (isDelete) {
delete foo.y;
}
var begin = new Date();
var result = 0;
for (var i = 0; i < number; i++) {
result = result + foo.x;
}
var end = new Date();
console.log('delete: %s, loop: %s, usetime: %d ms', isDelete, number, end - begin);
}
var number = parseInt(process.argv[2], 10) || 1000000;
console.log('prototypeDeleteBenchmark:');
prototypeDeleteBenchmark(number, false);
prototypeDeleteBenchmark(number, true);
console.log('propertyDeleteBenchmark:');
propertyDeleteBenchmark(number, false);
propertyDeleteBenchmark(number, true);
@jin52yang 不过对prototype进行delete的操作,目前我参与的项目中还没写过呢。。。
那就是说property delete 是没问题的吧。
反正 prototype delete从来没用过。
@guilin 是啊,property delete我用得蛮多的,于是就加上对比测试了。
@suqian 我没有实际场景需要用到这个;因为很喜欢Node,所以我最近在系统学习javascript中,这个我也是看到别人的测试用例,但是实在不明白为什么,我也没找到答案。
简单来说,V8认为多数数据的“结构是稳定”的,所以他就有一种优化方法,对一个类型生成一个对应的类,比如.prototype.x,他会生成带x属性的一个类,并通过静态的class这种类型,来引导x这个属性在对象所占内存中的偏移,同样再加上.prototype.y,就会生成有x和y两个属性的类
而问题就在这里,一但遇上delete,类型结构会被破坏,V8没办法通过预告固定的偏移(offset)值直接地获取某个属性的值,而必须一点一点地线性地查找,甚至需要在prototype链上查找属性,可以比较傻地理解为O(1)和O(n)的差距。
理论内容大家可以看看https://developers.google.com/v8/design#prop_access。
最后感谢灰大@otakustay 的解答。
赞!
有空整理一下。学习之
赞
@suqian delete可以完全删除实例属性,没试过删原型中的属性。
有理有据,令人信服