我偶然发现了这个jsperf结果:http://jsperf.com/delet-is-slow
它表明在javascript中使用delete
的速度很慢,但我不确定为什么会这样。什么是javascript引擎在幕后做的事情让事情变得缓慢?
答案 0 :(得分:8)
我认为问题不在于删除速度慢...简单删除操作的速度不值得测量......
您显示的JS perf链接执行以下操作:
该脚本显示迭代通过应用删除的数组比通过正常数组迭代慢。
您应该问问自己,为什么删除会使数组变慢?
引擎在内部将数组元素存储在连续的内存空间中,并使用数字索引器访问它们。
这就是他们所说的快速访问阵列。
如果删除此有序和连续索引中的一个元素,则强制数组变为字典模式...因此,之前数组中项的确切位置(索引器)成为关键在字典中,数组必须在其下搜索元素。
因此迭代变得缓慢,因为不再移动到内存中的下一个空间,但是你一遍又一遍地执行哈希搜索。
答案 1 :(得分:2)
你会在这里得到很多关于微优化的答案,但删除确实有时会出现最严重的问题,在人们必须在JS中注意到的某些场景中它会变得极其缓慢。这些是我所知道的边缘情况,可能适用于您,也可能不适用于您。
我建议在不同浏览器中进行配置和基准测试以检测这些异常情况。
老实说我不知道原因,因为我倾向于解决这个问题,但我猜想GC中的怪癖组合(它可能会被频繁调用),残酷的重复,对其他案例的优化和怪异对象结构/糟糕的时间复杂性。
案例通常涉及中等到大量的密钥,例如:
从具有多个键的对象中删除:
(function() {
var o={},s,i,c=console;
s=new Date();for(i=0;i<1000000;i+=10)o[i]=i;c.log('Set: '+(new Date()-s));
s=new Date();for(i=0;i<50000;i+=10)delete(o[i]);c.log('Delete: '+(new Date()-s));})();
铬: 设置:21 删除:2084
火狐: 设置:74 删除:2
我遇到过这方面的一些变化,并不总是很容易重现。签名通常似乎会以指数方式降级。在Firefox中的一个案例中,for循环内部的删除会降低到每秒3-6次左右的操作,而在迭代Object.keys时删除会很好。
我个人倾向于认为这些案例可以被视为错误。您会遇到大量无症状和不成比例的性能下降,您可以通过不会改变时间或空间复杂性的方式解决这些问题,或者甚至可能导致性能稍差。这意味着当被视为声明性语言时,JS会使实现/优化错误。到目前为止,我已经看到地图与删除没有相同的问题。