出于好奇,我决定在插入/添加和查找方面确认我认为Set实现比Object(在google chrome中运行)更快。我的结果有些令人困惑。
x = {};
y = new Set();
console.time('Insert into Object');
for (var i = 0; i < 1000000; i++) {
x[i] = 0;
}
console.timeEnd('Insert into Object');
console.time('Insert into Set');
for (i = 0; i < 1000000; i++) {
y.add(i);
}
console.timeEnd('Insert into Set');
var t = 0;
console.time('Retrieve from Object');
for (i = 0; i < 1000000; i++) {
t = x[i];
}
console.timeEnd('Retrieve from Object');
console.time('Retrieve from Set');
for (i = 0; i < 1000000; i++) {
t = y.has(i);
}
console.timeEnd('Retrieve from Set');
VM19742:9 Insert into Object: 1341.777ms
VM19742:15 Insert into Set: 1473.025ms
VM19742:23 Retrieve from Object: 1469.717ms
VM19742:29 Retrieve from Set: 1666.430ms
正如您所看到的,该集合的表现略差于Object。这让我感到困惑,因为我认为底层实现与对象完全相同,没有存储值的额外开销。有没有人对这是为什么有任何额外的见解?
答案 0 :(得分:3)
为了解决您的问题,为什么您认为存储值可能比检查现有值以查看是否需要存储它更慢?
为了完成,我修改了你的代码以包含数组。
x = {};
y = new Set();
z = [];
console.time('Insert into Object');
for (var i = 0; i < 1000000; i++) {
x[i] = 0;
}
console.timeEnd('Insert into Object');
console.time('Insert into Set');
for (i = 0; i < 1000000; i++) {
y.add(i);
}
console.timeEnd('Insert into Set');
console.time('Insert into Array');
for (i = 0; i < 1000000; i++) {
z[i] = 0;
}
console.timeEnd('Insert into Array');
var t = 0;
console.time('Retrieve from Object');
for (i = 0; i < 1000000; i++) {
t = x[i];
}
console.timeEnd('Retrieve from Object');
console.time('Retrieve from Set');
for (i = 0; i < 1000000; i++) {
t = y.has(i);
}
console.timeEnd('Retrieve from Set');
console.time('Retrieve from Array');
for (i = 0; i < 1000000; i++) {
t = z[i];
}
console.timeEnd('Retrieve from Array');
console.log(t);
通常,人们会期望存储到对象中是O(1)时间复杂度,而检查集合中的现有值应该不超过 O(n)(其中n是数字)对于集合中的项目,所以我们应该期望随着集合变大,集合可能会变慢。这种性能甚至可能依赖于实现,即不同的javascript运行时可能表现不同。
事实上,这正是我们所看到的:(在我的机器上运行)
(您的代码)
Insert into Object: 67.558ms
Insert into Set: 259.841ms
Insert into Array: 64.297ms
Retrieve from Object: 19.337ms
Retrieve from Set: 149.968ms
Retrieve from Array: 3.981ms
但是,如果我们更改您的插入测试以不断重新添加相同的值...
我们看到了:
Insert into Object: 19.103ms
Insert into Set: 40.645ms
Insert into Array: 16.384ms
Retrieve from Object: 40.116ms
Retrieve from Set: 30.672ms
Retrieve from Array: 70.050ms
这告诉我们一些事情。首先,不同类型对集合的大小不同。其次,从数组或对象中检索不存在的键比检查相同值的集合要慢(至少在此特定实现上)。
最后一点
我认为重要的是要注意,我们正在讨论在百万次迭代(或大约一秒半)的情况下,相对于一秒钟的事情的相对表现。测试)。这已经非常快了。对于那些将来阅读本文的人,请记住选择语义上您想要的数据结构。从性能角度来看,这三者中的任何一个都是非常好的选择。选择使您的程序最容易理解的那个。
答案 1 :(得分:0)
测试用例有点缺陷。
x.hasOwnProperty(key)
或x[key]!==undefined
。