MacBook Pro 13 (2015 early), 16GB RAM, macOS 10.15.1
Chrome 78.0.3904.108
Safari 13.0.3
Firefox 71.0
Node 10.15.1
// 生成测试数据
const dataToCache = [];
for (let i = 0; i < 1000; i++) {
dataToCache.push({
id: genGuid(),
balabala: "balabala"
});
}
添加缓存项
// 添加缓存数据
objCache = {};
run1wTimes("cache by Object - add item", () => {
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
objCache[data.id] = data;
}
});
setCache = new Set();
run1wTimes("cache by Set - add item", () => {
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
setCache.add(data);
}
});
多次执行结果如下:
# node
cache by Object - add item: 266.779ms
cache by Set - add item: 181.644ms
cache by Object - add item: 273.227ms
cache by Set - add item: 177.329ms
cache by Object - add item: 255.003ms
cache by Set - add item: 181.770ms
cache by Object - add item: 241.004ms
cache by Set - add item: 176.350ms
cache by Object - add item: 259.306ms
cache by Set - add item: 182.561ms
# chrome
cache by Object - add item: 233.2041015625ms
cache by Set - add item: 208.697021484375ms
cache by Object - add item: 242.2080078125ms
cache by Set - add item: 193.538330078125ms
cache by Object - add item: 228.8369140625ms
cache by Set - add item: 193.158935546875ms
cache by Object - add item: 241.336181640625ms
cache by Set - add item: 194.253173828125ms
cache by Object - add item: 226.299072265625ms
cache by Set - add item: 191.123046875ms
cache by Object - add item: 226.415771484375ms
cache by Set - add item: 196.301025390625ms
# Safari
cache by Object - add item: 628.628ms
cache by Set - add item: 429.687ms
cache by Object - add item: 671.169ms
cache by Set - add item: 438.944ms
cache by Object - add item: 625.141ms
cache by Set - add item: 421.651ms
cache by Object - add item: 620.798ms
cache by Set - add item: 434.040ms
cache by Object - add item: 630.158ms
cache by Set - add item: 431.311ms
# Firefox
# 耗时有点异常,但多次执行依然是这样
cache by Object - add item: 4624ms
cache by Set - add item: 3722ms
cache by Object - add item: 4557ms
cache by Set - add item: 3604ms
cache by Object - add item: 4612ms
cache by Set - add item: 3405ms
cache by Object - add item: 4510ms
cache by Set - add item: 4424ms
cache by Object - add item: 4659ms
cache by Set - add item: 3383ms
let objCache = {};
let setCache = new Set();
let temp;
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
objCache[data.id] = data;
}
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
setCache.add(data);
}
run1wTimes("cache by Object - forEach", () => {
for (const key in objCache) {
if (objCache.hasOwnProperty(key)) {
temp = objCache[key];
}
}
});
run1wTimes("cache by Set - forEach", () => {
setCache.forEach(item => {
temp = item;
});
});
多次执行结果:
# node
cache by Object - forEach: 1283.685ms
cache by Set - forEach: 143.221ms
cache by Object - forEach: 1321.415ms
cache by Set - forEach: 141.727ms
cache by Object - forEach: 1295.686ms
cache by Set - forEach: 140.379ms
cache by Object - forEach: 1318.022ms
cache by Set - forEach: 140.797ms
cache by Object - forEach: 1312.564ms
cache by Set - forEach: 143.722ms
# chrome
cache by Object - forEach: 1312.255859375ms
cache by Set - forEach: 141.73095703125ms
cache by Object - forEach: 1298.447021484375ms
cache by Set - forEach: 136.48193359375ms
cache by Object - forEach: 1326.23974609375ms
cache by Set - forEach: 139.885986328125ms
cache by Object - forEach: 1317.888916015625ms
cache by Set - forEach: 138.151123046875ms
cache by Object - forEach: 1387.4541015625ms
cache by Set - forEach: 136.711181640625ms
# Safari
cache by Object - forEach: 555.257ms
cache by Set - forEach: 312.070ms
cache by Object - forEach: 613.752ms
cache by Set - forEach: 291.776ms
cache by Object - forEach: 578.782ms
cache by Set - forEach: 294.459ms
cache by Object - forEach: 654.297ms
cache by Set - forEach: 321.344ms
cache by Object - forEach: 611.440ms
cache by Set - forEach: 308.352ms
# Firefox
cache by Object - forEach: 3362ms
cache by Set - forEach: 965ms
cache by Object - forEach: 3306ms
cache by Set - forEach: 952ms
cache by Object - forEach: 3359ms
cache by Set - forEach: 972ms
cache by Object - forEach: 3248ms
cache by Set - forEach: 1052ms
cache by Object - forEach: 3537ms
cache by Set - forEach: 973ms
let objCache = {};
let setCache = new Set();
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
objCache[data.id] = data;
}
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
setCache.add(data);
}
run1wTimes("cache by Object - delete item", () => {
const index = Math.floor(Math.random() * dataToCache.length);
const data = dataToCache[index];
delete objCache[data.id];
});
run1wTimes("cache by Set - delete item", () => {
const index = Math.floor(Math.random() * dataToCache.length);
const data = dataToCache[index];
setCache.delete(data);
});
多次执行结果:
# node
cache by Object - delete item: 5.210ms
cache by Set - delete item: 2.859ms
cache by Object - delete item: 2.591ms
cache by Set - delete item: 3.795ms
cache by Object - delete item: 2.434ms
cache by Set - delete item: 3.317ms
cache by Object - delete item: 2.535ms
cache by Set - delete item: 3.581ms
cache by Object - delete item: 3.331ms
cache by Set - delete item: 3.369ms
# chrome
cache by Object - delete item: 1.30517578125ms
cache by Set - delete item: 0.529052734375ms
cache by Object - delete item: 0.638916015625ms
cache by Set - delete item: 0.635986328125ms
cache by Object - delete item: 0.60498046875ms
cache by Set - delete item: 0.470947265625ms
cache by Object - delete item: 0.64404296875ms
cache by Set - delete item: 0.85986328125ms
cache by Object - delete item: 0.60400390625ms
cache by Set - delete item: 0.5068359375ms
# safari
cache by Object - delete item: 4.752ms
cache by Set - delete item: 2.998ms
cache by Object - delete item: 1.089ms
cache by Set - delete item: 0.771ms
cache by Object - delete item: 1.441ms
cache by Set - delete item: 0.866ms
cache by Object - delete item: 1.805ms
cache by Set - delete item: 1.583ms
cache by Object - delete item: 2.620ms
cache by Set - delete item: 1.560ms
# firefox
cache by Object - delete item: 16ms
cache by Set - delete item: 6ms
cache by Object - delete item: 11ms
cache by Set - delete item: 10ms
cache by Object - delete item: 8ms
cache by Set - delete item: 6ms
cache by Object - delete item: 14ms
cache by Set - delete item: 9ms
cache by Object - delete item: 7ms
cache by Set - delete item: 6ms
各测试环境下的删除操作,大多是 Set 更快一些 ,但在 Node 环境中 Object缓存反而更快。各幅度(Object 耗时 - Set 耗时) / Object 耗时分别是:
Node: -16.00%
Chrome: 12.93%
Safari: 31.75%
Firefox: 29.31%
Done。
结论就是,用作缓存时,增删和遍历操作,Set的性能更好。除了 Node 环境下的删除项操作。
追加:缓存简单数据类型
将测试数据改为简单数据类型(字符串),测试其添加缓存项:
const dataToCache = [];
for (let i = 0; i < 1000; i++) {
dataToCache.push(genGuid());
}
const objCache = {};
run1wTimes("cache by Object - add item", () => {
for (let i = 0; i < dataToCache.length; i++) {
const data = dataToCache[i];
objCache[data] = data;
}
});
const setCache = new Set();
run1wTimes("cache by Set - add item", () => {
for (let i = 0; i < dataToCache.length; i++) {
setCache.add(dataToCache[i]);
}
});
多次执行得到:
# node
cache by Object - add item: 234.102ms
cache by Set - add item: 405.451ms
cache by Object - add item: 230.297ms
cache by Set - add item: 367.350ms
cache by Object - add item: 236.763ms
cache by Set - add item: 413.732ms
cache by Object - add item: 221.878ms
cache by Set - add item: 387.975ms
cache by Object - add item: 239.362ms
cache by Set - add item: 380.882ms
# chrome
cache by Object - add item: 216.985107421875ms
cache by Set - add item: 276.950927734375ms
cache by Object - add item: 210.3837890625ms
cache by Set - add item: 270.06103515625ms
cache by Object - add item: 212.114990234375ms
cache by Set - add item: 271.041259765625ms
cache by Object - add item: 209.23828125ms
cache by Set - add item: 272.879150390625ms
cache by Object - add item: 207.015869140625ms
cache by Set - add item: 270.810791015625ms
# safari
cache by Object - add item: 599.806ms
cache by Set - add item: 420.768ms
cache by Object - add item: 588.941ms
cache by Set - add item: 425.122ms
cache by Object - add item: 583.876ms
cache by Set - add item: 419.824ms
cache by Object - add item: 590.346ms
cache by Set - add item: 429.632ms
cache by Object - add item: 579.668ms
cache by Set - add item: 423.003ms
# firefox
cache by Object - add item: 3470ms
cache by Set - add item: 3266ms
cache by Object - add item: 3598ms
cache by Set - add item: 3307ms
cache by Object - add item: 3534ms
cache by Set - add item: 3307ms
cache by Object - add item: 3503ms
cache by Set - add item: 3259ms
cache by Object - add item: 3651ms
cache by Set - add item: 3520ms
背景
最近又开始做表格的性能优化,优化过几波后,现在只能是抠一些细节。由于表格的单元格数量、公式数量常常是几十上百万,所以细节的改变也算是能带来不错的反馈。
这两天盯上的是各种缓存,目前基本上都是通过
Object
做的,key => value
。其中不少场景的数据本身没有 key,还得写专门生成 key 的方法。没错,现在就是准备用Set
代替 Object 来做数据的缓存。下面就通过几个测试来看看
Set
用作缓存有没有比Object
更快。TL; DR;
Set
缓存的的添加、遍历、删除项操作都比Object
缓存快不少,程度在不同的 JS 引擎下不等;Set
是按引用判断某元素是否已存在,因此不适合缓存每次新 new 的引用类型数据;Object
比Set
更快。但就Set
方面对比 Safari 和 Firefox,V8 的Set
还是最快的,所以也可以认为,V8 的Object
的实现太好了。Set 的基本信息
Set
对象能保存一系列数据的唯一值。对于 Object 元素,是直接判断的引用是否一致。另外,Set
提供了add
,delete
,clear
,forEach
等方法用于操作元素。其它
Set
的具体细节请查阅 MDN:Set - JavaScript | MDN下面开始测试性能吧~
测试环境
添加缓存项
多次执行结果如下:
各测试环境下,
Set
的添加项操作都比Object
快,各幅度(Object 耗时 - Set 耗时) / Object 耗时
分别是:遍历缓存项
多次执行结果:
各环境下,
Set
的添加项都比Object
快,各幅度(Object 耗时 - Set 耗时) / Object 耗时
分别是:删除缓存项
多次执行结果:
各测试环境下的删除操作,大多是
Set
更快一些 ,但在 Node 环境中Object
缓存反而更快。各幅度(Object 耗时 - Set 耗时) / Object 耗时
分别是:Done。
结论就是,用作缓存时,增删和遍历操作,
Set
的性能更好。除了 Node 环境下的删除项操作。追加:缓存简单数据类型
将测试数据改为简单数据类型(字符串),测试其添加缓存项:
多次执行得到:
可以看到,在不同的环境下,性能结果出现了相反的情况。V8 引擎下,
Object
更快;Safari 中Set
依然有明显优势;Firefox 中相差不大。具体幅度是:Others
完整测试代码
可以了解下