Javascript 集合与数组性能
这可能是因为 Sets 对 Javascript 来说相对较新,但我无法在 StackO 或其他任何地方找到一篇讨论 Javascript 中两者之间的性能差异的文章.那么,就性能而言,两者之间有什么区别?具体来说,在删除、添加和迭代方面.
It maybe because Sets are relatively new to Javascript but I haven't been able to find an article, on StackO or anywhere else, that talks about the performance difference between the two in Javascript. So, what is the difference, in terms of performance, between the two? Specifically, when it comes to removing, adding and iterating.
推荐答案
好的,我已经测试了从数组和集合中添加、迭代和删除元素.我运行了一个小"测试,使用 10 000 个元素和一个大"测试,使用 100 000 个元素.这是结果.
Ok, I have tested adding, iterating and removing elements from both an array and a set. I ran a "small" test, using 10 000 elements and a "big" test, using 100 000 elements. Here are the results.
无论添加多少元素,.push
数组方法似乎比 .add
set 方法快 4 倍左右.
It would seem that the .push
array method is about 4 times faster than the .add
set method, no matter the number of elements being added.
对于这部分测试,我使用 for
循环来迭代数组,并使用 for of
循环来迭代集合.同样,遍历数组更快.这一次似乎是指数级的,因为在小"测试期间花费了两倍的时间,在大"测试期间花费了几乎四倍的时间.
For this part of the test I used a for
loop to iterate over the array and a for of
loop to iterate over the set. Again, iterating over the array was faster. This time it would seem that it is exponentially so as it took twice as long during the "small" tests and almost four times longer during the "big" tests.
这就是有趣的地方.我使用了 for
循环和 .splice
的组合从数组中删除一些元素,我使用了 for of
和 .delete
从集合中删除一些元素.对于小"测试,从集合中删除项目的速度大约快三倍(2.6 毫秒对 7.1 毫秒),但对于大"测试,情况发生了巨大变化,从数组中删除项目需要 1955.1 毫秒,而它只将它们从集合中移除需要 83.6 毫秒,快 23 倍.
Now this is where it gets interesting. I used a combination of a for
loop and .splice
to remove some elements from the array and I used for of
and .delete
to remove some elements from the set. For the "small" tests, it was about three times faster to remove items from the set (2.6 ms vs 7.1 ms) but things changed drastically for the "big" test where it took 1955.1 ms to remove items from the array while it only took 83.6 ms to remove them from the set, 23 times faster.
在 10k 个元素时,两个测试的运行时间相当(数组:16.6 毫秒,集合:20.7 毫秒),但在处理 100k 个元素时,集合是明显的赢家(数组:1974.8 毫秒,集合:83.6 毫秒),但这仅仅是因为的删除操作.否则数组会更快.我不能确切地说这是为什么.
At 10k elements, both tests ran comparable times (array: 16.6 ms, set: 20.7 ms) but when dealing with 100k elements, the set was the clear winner (array: 1974.8 ms, set: 83.6 ms) but only because of the removing operation. Otherwise the array was faster. I couldn't say exactly why that is.
我尝试了一些混合场景,其中创建并填充了一个数组,然后将其转换为一个集合,其中一些元素将被删除,然后该集合将被重新转换为一个数组.尽管这样做会比删除数组中的元素提供更好的性能,但与集合之间传输所需的额外处理时间超过了填充数组而不是集合的收益.最后,只处理一组会更快.尽管如此,这是一个有趣的想法,如果一个人选择使用数组作为一些没有重复的大数据的数据集合,那么如果需要在一个中删除许多元素,这可能会在性能方面具有优势操作,将数组转换为集合,执行删除操作,并将集合转换回数组.
I played around with some hybrid scenarios where an array was created and populated and then converted into a set where some elements would be removed, the set would then be reconverted into an array. Although doing this will give much better performance than removing elements in the array, the additional processing time needed to transfer to and from a set outweighs the gains of populating an array instead of a set. In the end, it is faster to only deal with a set. Still, it is an interesting idea, that if one chooses to use an array as a data collection for some big data that doesn't have duplicates, it could be advantageous performance wise, if there is ever a need to remove many elements in one operation, to convert the array to a set, perform the removal operation, and convert the set back to an array.
数组代码:
var timer = function(name) {
var start = new Date();
return {
stop: function() {
var end = new Date();
var time = end.getTime() - start.getTime();
console.log('Timer:', name, 'finished in', time, 'ms');
}
}
};
var getRandom = function(min, max) {
return Math.random() * (max - min) + min;
};
var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];
var genLastName = function() {
var index = Math.round(getRandom(0, lastNames.length - 1));
return lastNames[index];
};
var sex = ["Male", "Female"];
var genSex = function() {
var index = Math.round(getRandom(0, sex.length - 1));
return sex[index];
};
var Person = function() {
this.name = genLastName();
this.age = Math.round(getRandom(0, 100))
this.sex = "Male"
};
var genPersons = function() {
for (var i = 0; i < 100000; i++)
personArray.push(new Person());
};
var changeSex = function() {
for (var i = 0; i < personArray.length; i++) {
personArray[i].sex = genSex();
}
};
var deleteMale = function() {
for (var i = 0; i < personArray.length; i++) {
if (personArray[i].sex === "Male") {
personArray.splice(i, 1)
i--
}
}
};
var t = timer("Array");
var personArray = [];
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personArray.length + " persons.")
设置代码:
var timer = function(name) {
var start = new Date();
return {
stop: function() {
var end = new Date();
var time = end.getTime() - start.getTime();
console.log('Timer:', name, 'finished in', time, 'ms');
}
}
};
var getRandom = function (min, max) {
return Math.random() * (max - min) + min;
};
var lastNames = ['SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON','MOORE','TAYLOR','ANDERSON','THOMAS'];
var genLastName = function() {
var index = Math.round(getRandom(0, lastNames.length - 1));
return lastNames[index];
};
var sex = ["Male", "Female"];
var genSex = function() {
var index = Math.round(getRandom(0, sex.length - 1));
return sex[index];
};
var Person = function() {
this.name = genLastName();
this.age = Math.round(getRandom(0,100))
this.sex = "Male"
};
var genPersons = function() {
for (var i = 0; i < 100000; i++)
personSet.add(new Person());
};
var changeSex = function() {
for (var key of personSet) {
key.sex = genSex();
}
};
var deleteMale = function() {
for (var key of personSet) {
if (key.sex === "Male") {
personSet.delete(key)
}
}
};
var t = timer("Set");
var personSet = new Set();
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personSet.size + " persons.")
相关文章