Skip to content

Instantly share code, notes, and snippets.

@jung-kim
Last active May 25, 2023 07:01
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jung-kim/83676b2310c7c2a9c3d8 to your computer and use it in GitHub Desktop.
Save jung-kim/83676b2310c7c2a9c3d8 to your computer and use it in GitHub Desktop.
es6 map vs array vs obj performance test
"use strict";
let looper = (callback) => {
let n = 2000000;
while (n > 0) {
callback(n);
n--;
}
}
let timer = (log, callback) => {
let start = Date.now();
callback()
console.log(log, Date.now() - start);
}
let map = new Map();
let obj = {};
let ray = [];
timer('Map int key set took: ', () => looper(index => map.set(Math.random() * 2000000, index)));
timer('Obj int key set took: ', () => looper(index => obj[Math.random() * 2000000] = index));
timer('ray int key set took: ', () => looper(index => ray[Math.random() * 2000000] = index));
console.log();
timer('Map int key get took: ', () => looper(index => {let dummylet = map.get(Math.random() * 2000000) }));
timer('Obj int key get took: ', () => looper(index => {let dummylet = obj[Math.random() * 2000000] }));
timer('ray int key get took: ', () => looper(index => {let dummylet = ray[Math.random() * 2000000] }));
console.log('\n\n');
map = new Map();
obj = {};
ray = [];
timer('Map string key set took: ', () => looper(index => map.set('' + Math.random() * 2000000, '' + index)));
timer('Obj string key set took: ', () => looper(index => obj['' + Math.random() * 2000000] = '' + index));
timer('ray string key set took: ', () => looper(index => ray['' + Math.random() * 2000000] = '' + index));
console.log();
timer('Map string key get took: ', () => looper(index => {let dummylet = map.get('' + Math.random() * 2000000) }));
timer('Obj string key get took: ', () => looper(index => {let dummylet = obj['' + Math.random() * 2000000] }));
timer('ray string key get took: ', () => looper(index => {let dummylet = ray['' + Math.random() * 2000000] }));
// // Example output in node v8
//
// Map int key set took: 1072
// Obj int key set took: 2460
// ray int key set took: 3457
//
// Map int key get took: 824
// Obj int key get took: 1609
// ray int key get took: 2246
//
//
//
// Map string key set took: 1580
// Obj string key set took: 2933
// ray string key set took: 2149
//
// Map string key get took: 1511
// Obj string key get took: 1575
// ray string key get took: 1818
@zen0wu
Copy link

zen0wu commented Jan 13, 2022

The fact that array is slower than Map makes little sense to me.

Here's a updated benchmark:

"use strict";

let looper = (callback) => {
  let n = 2000000;
  while (n > 0) {
    callback(n);
    n--;
  }
};

let timer = (log, callback) => {
  let start = Date.now();
  callback();
  console.log(log, Date.now() - start);
};

let map = new Map();
let obj = {};
let ray = [];

for (let i = 0; i < 2000000; i++) {
  ray.push(i);
}

function RandomIndex(count) {
  return Math.floor(Math.random() * count);
}

timer("Map int key set took: ", () =>
  looper((index) => map.set(RandomIndex(2000000), index))
);
timer("Obj int key set took: ", () =>
  looper((index) => (obj[RandomIndex(2000000)] = index))
);
timer("ray int key set took: ", () =>
  looper((index) => (ray[RandomIndex(2000000)] = index))
);
console.log();
timer("Map int key get took: ", () =>
  looper((index) => {
    let dummylet = map.get(RandomIndex(2000000));
  })
);
timer("Obj int key get took: ", () =>
  looper((index) => {
    let dummylet = obj[RandomIndex(2000000)];
  })
);
timer("ray int key get took: ", () =>
  looper((index) => {
    let dummylet = ray[RandomIndex(2000000)];
  })
);

console.log("\n\n");

map = new Map();
obj = {};
ray = [];

timer("Map string key set took: ", () =>
  looper((index) => map.set("" + RandomIndex(2000000), "" + index))
);
timer("Obj string key set took: ", () =>
  looper((index) => (obj["" + RandomIndex(2000000)] = "" + index))
);
timer("ray string key set took: ", () =>
  looper((index) => (ray["" + RandomIndex(2000000)] = "" + index))
);
console.log();
timer("Map string key get took: ", () =>
  looper((index) => {
    let dummylet = map.get("" + RandomIndex(2000000));
  })
);
timer("Obj string key get took: ", () =>
  looper((index) => {
    let dummylet = obj["" + RandomIndex(2000000)];
  })
);
timer("ray string key get took: ", () =>
  looper((index) => {
    let dummylet = ray["" + RandomIndex(2000000)];
  })
);

Two key points:

  1. As @FishOrBear pointed out, in the first test, the index needs to be integer, array is designed to be "an array", which doesn't support float keys.
  2. do not leave holes in array, when initializing, push the data as they go, where in the original benchmark, the array can have arbitrary gaps, which stops v8 from optimizing.

updated results

Map int key set took:  449
Obj int key set took:  432
ray int key set took:  45

Map int key get took:  31
Obj int key get took:  32
ray int key get took:  33



Map string key set took:  1176
Obj string key set took:  756
ray string key set took:  1234

Map string key get took:  33
Obj string key get took:  439
ray string key get took:  393

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment