以下是测试性能的环境
CPU | AMD Ryzen 9 5900HX with Radeon Graphics 八核 |
操作系统 | Windows 11 家庭中文版 (64位) |
内存 | 16GB(3200 MHz / 3200 MHz) |
Nodejs | v18.16.0 |
测试一:循环赋值
Array
const arr = [];
console.time('数组')
for (let i = 0; i < time; i++) {
arr.push(i);
}
console.timeEnd('数组')
Set
const set = new Set();
console.time('set')
for (let i = 0; i < time; i++) {
set.add(i);
}
console.timeEnd('set')
Map
const map = new Map();
console.time('map')
for (let i = 0; i < time; i++) {
map.set(i, undefined);
}
console.timeEnd('map')
Object
const obj = {};
console.time('对象')
for (let i = 0; i < time; i++) {
obj[i] = undefined;
}
console.timeEnd('对象')
测试结果
数组和对象的插入速度很快。
Nodejs
类型 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | 0.4ms | 4ms | 20ms | 210ms |
Set | 0.7ms | 6ms | 72ms | 2.2s |
对象 | 0.26ms | 3ms | 23ms | 592ms |
Map | 1.24ms | 7ms | 110ms | 2.7s |
测试二:数组赋值
Set
const setArr = [];
for (let i = 0; i < time; i++) {
setArr.push(i);
}
console.time('set')
const set = new Set(setArr);
console.timeEnd('set')
Map
const mapArr = [];
for (let i = 0; i < time; i++) {
mapArr.push([i, undefined]);
}
console.time('map')
const map = new Map(mapArr);
console.timeEnd('map')
测试结果
Nodejs
类型 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
Set | 0.7ms | 6ms | 89ms | 2.4s |
Map | 0.59ms | 7ms | 152ms | 3.5s |
测试三:循环遍历
Array
console.time('数组 forEach')
arr.forEach(val => {});
console.timeEnd('数组 forEach')
console.time('数组 for...in')
for (let i in arr) {
arr[i];
}
console.timeEnd('数组 for...in')
console.time('数组 for...of')
for (let val of arr) {}
console.timeEnd('数组 for...of')
console.time('数组 for')
const length = arr.length;
for (let i; i < length; i++) {
arr[i];
}
console.timeEnd('数组 for')
Set
console.time('set forEach')
set.forEach(val => {});
console.timeEnd('set forEach')
console.time('set for...of')
for (let val of set) {}
console.timeEnd('set for...of')
Map
console.time('map forEach')
map.forEach((val, key) => {});
console.timeEnd('map forEach')
console.time('map for...of')
for (let val of map) {}
console.timeEnd('map for...of')
Object
console.time('对象 forEach')
Object.keys(obj).forEach((key) => {})
console.timeEnd('对象 forEach')
console.time('对象 for...in')
for (let key in obj) {
obj[key]
}
console.timeEnd('对象 for...in')
测试结果
数组的普通for循环在大数据量的情况下速度非常快,比forEach快了太多了。
普通对象的遍历性能非常低(虽然在插入数据的时候要比Map和Set快),如果要对哈希表数据结构做遍历操作,还是建议使用Map或Set。
Nodejs
类型 | 方法 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | forEach | 0.107ms | 1.054ms | 5.598ms | 50.962ms |
for...in | 0.762ms | 6.372ms | 103.741ms | 1.369s |
for...of | 0.614ms | 3.906ms | 28.793ms | 97.9ms |
for | 0.104ms | 1.251ms | 3.016ms | 7.216ms |
Set | forEach | 0.102ms | 0.922ms | 5.537ms | 43.978ms |
for...of | 0.167ms | 3.458ms | 8.406ms | 57.894ms |
Map | forEach | 0.104ms | 0.867ms | 5.886ms | 47.26ms |
for...of | 0.461ms | 3.486ms | 17.414ms | 133.956ms |
对象 | forEach | 0.206ms | 5.356ms | 87.389ms | 1.612s |
for...in | 0.424ms | 7.009ms | 98.209ms | 1.921s |
测试四:随机查询
Array
console.time('数组')
for (let i = 0; i < time; i++) {
const tmp = arr[i];
}
console.timeEnd('数组')
Map
console.time('map')
for (let i = 0; i < time; i++) {
const tmp = map.get(i);
}
console.timeEnd('map')
Object
console.time('对象')
for (let i = 0; i < time; i++) {
const tmp = obj[i];
}
console.timeEnd('对象')
测试结果
Nodejs
类型 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | 0.263ms | 1.12ms | 1.633ms | 5.835ms |
对象 | 0.141ms | 1.113ms | 1.392ms | 5.425ms |
Map | 0.43ms | 4.434ms | 41.235ms | 455.84ms |
测试五:判断数据存不存在
Array
console.time('数组')
for (let i = 0; i < time; i++) {
if (arr[i]) {}
}
console.timeEnd('数组')
Map
console.time('对象')
for (let i = 0; i < time; i++) {
if (obj[i]) {}
}
console.timeEnd('对象')
Set
console.time('set')
for (let i = 0; i < time; i++) {
if(set.has(i)) {}
}
console.timeEnd('set')
Object
console.time('map')
for (let i = 0; i < time; i++) {
if(map.has(i)) {}
}
console.timeEnd('map')
测试结果
Nodejs
类型 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | 0.241ms | 1.119ms | 1.666ms | 5.662ms |
对象 | 0.141ms | 1.161ms | 1.693ms | 5.785ms |
Set | 0.325ms | 4.785ms | 51.14ms | 803.376ms |
Map | 0.354ms | 4.835ms | 48.093ms | 449.937ms |
测试五:随机删除
Array
console.time('数组')
for (let i = 0; i < time; i++) {
arr.splice(i, 1);
}
console.timeEnd('数组')
Map
console.time('对象')
for (let i = 0; i < time; i++) {
delete obj[i];
}
console.timeEnd('对象')
Set
console.time('set')
for (let i = 0; i < time; i++) {
set.delete(i);
}
console.timeEnd('set')
Object
console.time('map')
for (let i = 0; i < time; i++) {
map.delete(i)
}
console.timeEnd('map')
测试结果
数组是从后往前删的,严格意义讲不算随即删除,后续会单独补充CASE测试一下
Nodejs
类型 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | 1.368ms | 5.185ms | 35.957ms | 255.075ms |
对象 | 0.773ms | 5.272ms | 48.731ms | 421.327ms |
Set | 0.78ms | 7.587ms | 97.004ms | 1.734s |
Map | 0.914ms | 9.43ms | 113.456ms | 1.930s |
测试六:指定size和不指定size的区别
const time = 10000 * 1000;
const randomArr = [];
for (let i = 0; i < time; i++) {
randomArr.push(Math.random() * time >> 0);
}
console.time('数组,不指定size, push')
const arr = [];
for (let i = 0; i < time; i++) {
arr.push(i);
}
console.timeEnd('数组,不指定size, push')
console.time('数组,不指定size, shift')
const arr1 = [];
for (let i = 0; i < time; i++) {
arr1.unshift(i);
}
console.timeEnd('数组,不指定size, shift')
console.time('数组,不指定size, 正序')
const arr2 = [];
for (let i = 0; i < time; i++) {
arr2[i] = 0;
}
console.timeEnd('数组,不指定size, 正序')
console.time('数组,不指定size, 倒序')
const arr3 = [];
for (let i = time - 1; i >= 0; i--) {
arr3[i] = i;
}
console.timeEnd('数组,不指定size, 倒序')
console.time('数组,不指定size, 随机')
const arr4 = [];
for (let i = time - 1; i >= 0; i--) {
arr4[randomArr[i]] = i;
}
console.timeEnd('数组,不指定size, 随机')
console.time('数组,指定size,正序')
const arr5 = new Array(time);
for (let i = 0; i < time; i++) {
arr5[i] = 0;
}
console.timeEnd('数组,指定size,正序');
console.time('数组,指定size,倒序')
const arr6 = new Array(time);
for (let i = 0; i < time; i++) {
arr6[i] = 0;
}
console.time('数组,指定size,倒序')
console.time('数组,指定size,随机')
const arr7 = new Array(time);
for (let i = time - 1; i >= 0; i--) {
arr7[randomArr[i]] = i;
}
console.time('数组,指定size,随机')
console.time('数组,指定size,随机,非稀疏数组')
const arr8 = new Array(time).fill(undefined);
for (let i = time - 1; i >= 0; i--) {
arr8[randomArr[i]] = i;
}
console.timeEnd('数组,指定size,随机,非稀疏数组')
测试结果
数组是从后往前删的,严格意义讲不算随即删除,后续会单独补充CASE测试一下
Nodejs
类型 | 指定size | 初始化 | 方法 | 顺序 | 1万次 | 10万次 | 100万次 | 1000万次 |
---|
数组 | 否 | - | push | 正序 | 1.12ms | 3.534ms | 18.844ms | 215.098ms |
否 | - | unshift | 倒序 | 7.502ms | 677.837ms | 1:08.297 (m:ss.mmm) | 时间太久放弃 |
否 | - | 随机存储
| 正序 | 0.74ms | 4.047ms | 22.124ms | 199.869ms |
否 | - | 随机存储 | 倒序 | 0.571ms | 6.463ms | 63.207ms | 1.391s |
否 | - | 随机存储 | 随机 | 1.336ms | 8.192ms | 85.356ms | 1.881s |
是 | 否 | 随机存储 | 正序 | 0.526ms | 4.254ms | 5.39ms | 60.065ms |
是 | 否 | 随机存储 | 倒序 | 0.171ms | 5.827ms | 5.513ms | 45.6ms |
是 | 否 | 随机存储 | 随机 | 0.241ms | 2.449ms | 10.456ms | 182.37ms |
是 | 是 | 随机存储 | 随机 | 0.277ms | 1.917ms | 8.862ms | 168.578ms |