V8引擎对JS数组的一些实现优化

先来2个例子吧:

var t = new Array(200000); console.time('time1'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time1');
var t = []; console.time('time2'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time2');

各位可以在各个浏览器控制台下看看输出情况, 我这的情况大概如下:

chrome

time1: 59109.000ms

time2: 379.000ms

FireFox

time1: 509ms

time2: 461ms

IE

time1: 351ms

time2: 356ms

在StackOverflow上看到的结论如下:

如果数组索引从0到length-1,而又无洞(注:洞的意思即存在索引所指向的元素未赋值),那么这个引擎会用C语言的数组来实现,因此会非常快。

如果在数组中有洞,引擎将会用哈希表来实现,这会比C数组慢许多。

例外情况是:如果预分配的数组长度小于100000, 引擎依然会用C数组实现,此时该数组有洞又有速度0- -!

以下代码说明了这点:

var t = new Array(99999); console.time('time1'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time1');
var t = new Array(99999+1); console.time('time2'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time2');

chrome下运行结果如下:

time1: 447.00ms

time2: 4110.000msms

不止这些,再来2个更神奇的例子:

var t = new Array(180000); console.time('time1'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time1');
var t = new Array(181000); console.time('time2'); for (var i = 0; i < 200000; ++i) {t.push(1);} console.timeEnd('time2');

chrome输出如下:

time1: 4165.000ms

time1: 59034.000ms

对此解释如下:

V8引擎的启发式算法会将符合条件的处于字典(哈希表)模式的数组转化为快速(C数组)模式。 当数组处于字典模式,在它每次要增长时,V8会检查数组是否足够紧缩,且使用连续的C数组替代字典数组是否能在空间上更有优势。

在上面的2个例子中,第一个例子被替换为了C数组, 第二个例子在空间上不具备更大的优势,则未回退。

总结

V8对数组的优化步骤如下:

  1. 预分配数组长度小于等于100000,或数组无洞,底层采用C数组实现;空间换时间

  2. 预分配数组长度大于100000,数组有洞,底层采用哈希表实现;时间换空间

  3. 处于字典模式(哈希表实现)的数组,在每次空间增长时,V8的启发式算法会检查其空间占用量, 若其空洞元素减少到一定程度,则会将其转化为高速模式(C数组)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值