Closed
Description
I was benchmarking different data structures and noticed a huge slowdown for the following test case:
- Create an object with a bunch 20-character string properties, the value is always set to the number 1.
- Loop over each key: delete it from the object and add it back.
The performance of object and Map is roughly the same in Node 11.15.0. In Node 12, the object version gets really slow (~10x slower for a 100-element object, ~60x slower for a 1000-element object).
Here's my full test case:
"package.json"
{
"dependencies": {
"benchmark": "2.1.4"
}
}
"main.js"
const Benchmark = require('benchmark')
const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ';
function randomString(length) {
const parts = [];
for (let i = 0; i < length; i++) {
parts.push(digits.charAt(Math.random() * digits.length));
}
return parts.join('');
}
console.log(`Node ${process.versions.node}, V8 ${process.versions.v8}`);
for (const size of [10, 100, 1000, 10000]) {
const keys = []
const object = {};
const map = new Map();
for (let i = 0; i < size; i++) {
const key = randomString(20);
keys.push(key);
object[key] = 1;
map.set(key, 1);
}
const suite = new Benchmark.Suite();
{
let keyI = 0;
suite.add('Object', () => {
const key = keys[keyI++];
if (keyI >= keys.length) {
keyI = 0;
}
delete object[key];
object[key] = 1;
});
}
{
let keyI = 0;
suite.add('Map', () => {
const key = keys[keyI++];
if (keyI >= keys.length) {
keyI = 0;
}
map.delete(key);
map.set(key, 1);
});
}
suite.on('cycle', event => {
console.log(' ' + String(event.target));
});
console.log(`size: ${size}`);
suite.run();
}
Results
Node 11.15.0, V8 7.0.276.38-node.19
size: 10
Object x 12,638,709 ops/sec ±2.40% (88 runs sampled)
Map x 18,837,340 ops/sec ±1.18% (88 runs sampled)
size: 100
Object x 18,198,146 ops/sec ±1.08% (92 runs sampled)
Map x 16,736,960 ops/sec ±2.69% (81 runs sampled)
size: 1000
Object x 9,668,335 ops/sec ±4.26% (75 runs sampled)
Map x 14,076,212 ops/sec ±2.19% (81 runs sampled)
size: 10000
Object x 7,074,321 ops/sec ±1.51% (86 runs sampled)
Map x 11,127,011 ops/sec ±1.69% (87 runs sampled)
Node 12.0.0, V8 7.4.288.21-node.16
size: 10
Object x 5,006,773 ops/sec ±10.47% (41 runs sampled)
Map x 18,186,938 ops/sec ±1.41% (90 runs sampled)
size: 100
Object x 1,026,833 ops/sec ±115.69% (9 runs sampled)
Map x 16,332,681 ops/sec ±2.39% (85 runs sampled)
size: 1000
Object x 204,617 ops/sec ±226.52% (9 runs sampled)
Map x 14,577,494 ops/sec ±1.44% (87 runs sampled)
size: 10000
Object x 89,706 ops/sec ±202.29% (26 runs sampled)
Map x 11,407,806 ops/sec ±2.25% (86 runs sampled)
Node 12.6.0, V8 7.5.288.22-node.14
size: 10
Object x 4,848,704 ops/sec ±8.96% (47 runs sampled)
Map x 13,350,969 ops/sec ±1.14% (87 runs sampled)
size: 100
Object x 1,331,497 ops/sec ±128.56% (11 runs sampled)
Map x 14,494,479 ops/sec ±1.71% (86 runs sampled)
size: 1000
Object x 360,305 ops/sec ±208.01% (14 runs sampled)
Map x 11,921,007 ops/sec ±1.29% (88 runs sampled)
size: 10000
Object x 74,324 ops/sec ±202.57% (27 runs sampled)
Map x 10,444,440 ops/sec ±1.14% (89 runs sampled)