ES6 Map vs Object properties (v36)

Revision 36 of this benchmark created by Brandon Papworth on


Description

Compare native Map implementation vs using an object as a hash map. Added 2 optimized tests for iterating the hash map.

Preparation HTML

<script>
;(function(window, floor, random){'use strict';
    var pc = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").split('');
    var len = pc.length;

    function randomString() {
        /// Will do this 5 times
        return pc[floor(random() * len)]
             + pc[floor(random() * len)]
             + pc[floor(random() * len)]
             + pc[floor(random() * len)]
             + pc[floor(random() * len)]
        ;
    }
    window.randomString = randomString;
})(window, Math.floor, Math.random);
;(function(window){'use strict';
    function EnumVal(name) { this.name = name; }
    EnumVal.prototype.toString = function enumValToString() { return this.name; };
    EnumVal.prototype.toJSON = function enumValToJSON() { return {name: this.name}; };
    window.EnumVal = EnumVal;
})(window);
;(function(window, Map, EnumVal, random, randomString){'use strict';
    function createNewJsMap(iterableObj) {
        return iterableObj ? new Map(iterableObj) : new Map();
    }
    function createNullProtoObject() { return Object.create(null); }
    function generateArrayOfTuples() {
        var i = 0;
        var tupleArray = [];
        do {
            tupleArray.push([randomString(), randomString()]);       
            i += 1;
        } while(i < 1000);
        return tupleArray;
    }

    function __mapCb_addRandom(el) {
        return [random(),el]; /// randomAndEl
    }
    function __mapCb_pluckKey(randomAndEl) {
        return randomAndEl[1][0];
    }
    function __sortCb_byFirstEl(randomAndEl_a, randomAndEl_b) {
        return randomAndEl_a[0] < randomAndEl_b[0];
    }
    function __mapCb_keyToEnumVal(el) {
        return [new EnumVal(el[0]), el[1]];
    }

    function shuffledArrayOfTuples(tuplesArray) {
        return tuplesArray
            .map(__mapCb_addRandom)
            .sort(__sortCb_byFirstEl)
            .map(__mapCb_pluckKey)
    }

    function enumeratedKeysForArrayOfTuples(tuplesArray) {
        return tuplesArray
            .map(__mapCb_keyToEnumVal)
        ;
    }

    window.createNewJsMap                 = createNewJsMap;
    window.createNullProtoObject          = createNullProtoObject;
    window.generateArrayOfTuples          = generateArrayOfTuples;
    window.shuffledArrayOfTuples          = shuffledArrayOfTuples;
    window.enumeratedKeysForArrayOfTuples = enumeratedKeysForArrayOfTuples;
})(window, window.Map, window.EnumVal, Math.random, window.randomString);
</script>

Setup

var arrayOfTuples = generateArrayOfTuples();
    var enumTuples    = enumeratedKeysForArrayOfTuples(arrayOfTuples);
    var map           = window.createNewJsMap();
    var map0          = window.createNewJsMap();
    var map2          = window.createNewJsMap(arrayOfTuples);
    var map3          = window.createNewJsMap(enumTuples);
    var obj           = window.createNullProtoObject();
    var obj2          = window.createNullProtoObject();
    var obj3          = window.createNullProtoObject();
    var pkeys         = shuffledArrayOfTuples(arrayOfTuples);
    var pkeysEnum     = shuffledArrayOfTuples(enumTuples);
    
    for (var i=0, L=arrayOfTuples.length; i < L; i+=1) {
        obj2[arrayOfTuples[0]]         = arrayOfTuples[1];
        obj3[enumTuples[0].toString()] = enumTuples[1];
    }

Test runner

Ready to run.

Testing in
TestOps/sec
map.set(key,val)
for (var i=0; i < 1000; i+=1) {
   map.set(randomString(), randomString());
}
ready
map.set(enumValKey, val)
for (var i=0; i < 1000; i+=1) {
   map0.set(new EnumVal(randomString()), randomString());
}
ready
obj[key] = val;
for (var i=0; i < 1000; i+=1) {
   obj[randomString()] = randomString();
}
ready
obj[enumValKey] = val;
for (var i=0; i < 1000; i+=1) {
   obj[new EnumVal(randomString())] = randomString();
}
ready
Iterate Map
for (var key of map2.keys()) {
  var val = map2.get(key);
}
ready
Iterate Map EnumVal
for (var key of map3.keys()) {
  var val = map3.get(key);
}
ready
Iterate Object
for (var key of Object.keys(obj2)) {
  var val = obj2[key];
}
ready
Iterate Object Keys
var keys = Object.keys(obj2);
for (var i = 0, length = keys.length; i < length; i++) {
    var val = obj2[keys[i]];
}
ready
Iterate Object Keys EnumVal
var keys = Object.keys(obj3);
for (var i = 0, length = keys.length; i < length; i++) {
    var val = obj3[keys[i]];
}
ready
Iterate Object no hasOwnProperty check
var key;
for (key in obj2) {
    var val = obj2[key];
}
ready
Iterate Object no hasOwnProperty check EnumVal
var key;
for (key in obj3) {
    var val = obj3[key];
}
ready
Iterate Object Precomputed Keys
for (var i = 0, length = pkeys.length; i < length; i++) {
    var val = obj2[pkeys[i]];
}
ready
Iterate Object Precomputed EnumVal Keys
for (var i = 0, length = pkeysEnum.length; i < length; i+=1) {
    var val = obj3[pkeysEnum[i]];
}
ready
Iterate Map Precomputed Keys
for (var i = 0, length = pkeys.length; i < length; i+=1) {
    var val = map2.get(pkeys[i]);
}
ready
Iterate Map Precomputed EnumVal Keys
for (var i = 0, length = pkeysEnum.length; i < length; i+=1) {
    var val = map3.get(pkeysEnum[i]);
}
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.