为什么在新节点版本中创建具有字母数字键的对象如此之慢?

时间:2015-07-22 05:35:05

标签: javascript node.js performance

我在不同的节点版本中运行此测试:

function test() {
    var i;
    var bigArray = {};

    var start = new Date().getTime();

    for (i=0; i<100000; i+=1) {
        bigArray[i] = {};
        var j= Math.floor(Math.random() * 10000000);
        bigArray[i]["a" + j] = i.toString(32);
        if (i % 1000 === 0) console.log(i);
    }

    var end = new Date().getTime();
    var time = end - start;
    console.log('Execution time: ' + time);
}

test();

如您所见,它只创建一个包含100000个字段的对象,其中每个字段只是一个只有一个字段的对象。该内部对象的键被强制为字母数字(如果键是数字,则表示正常)。

当我在不同的javascript实现/版本中运行此测试时,我得到了这样的结果:

v0.8.28     ->  2716 ms
v0.10.40    -> 73570 ms
v0.12.7     -> 92427 ms
iojs v2.4.0 ->   510 ms
chrome      ->  1473 ms

我还尝试在异步循环中运行此测试(每个循环步骤以不同的方式),但结果与上面显示的类似。

我无法理解为什么这个测试在较新的节点版本中如此昂贵。 为什么这么慢? 是否有任何特殊的v8标志可以改善此测试?

1 个答案:

答案 0 :(得分:1)

为了处理大型和稀疏数组,内部有两种类型的数组存储:

  • 快速元素:紧凑型密钥集的线性存储
  • 词典元素:否则为哈希表存储

最好不要让阵列存储从一种类型转换到另一种类型。

因此:

  • 使用从0开始的连续键(Arrays
  • 不要将大型数组(例如> 64K元素)预先分配到最大尺寸,而是随着时间的推移而增长
  • 不要删除数组中的元素,尤其是数值数组
  • 不加载未初始化或已删除的元素

来源和更多信息:http://www.html5rocks.com/en/tutorials/speed/v8/

PS:在即将推出的node.js + io.js版本中,这应该会大大改善。