简体   繁体   中英

Higher perf - Map.prototype.forEach or for..of?

Say I have:

const m = new Map();

is there a performance difference between:

for(let v of m){

}

vs.

m.forEach(v => {});

I assume Map.protoype.forEach uses an iterator just like for..of? I read here that's it safe to delete keys from the map during iteration using for..of, see: ES6: Is it dangerous to delete elements from Set/Map during Set/Map iteration?

and I am wondering if it's safe to delete keys from the map with a Map.prototype.forEach loop also.

I was also interested in this and created a JSPerf benchmark that performs a simple raw iteration over a map but doesn't do anything with the entries themselves.

A for-of loop like the following:

for (let entry of testMap) ...

consistently performs about 15-20% faster in chrome when it comes to just iterating over the entire thing, compared to forEach.

If you need better readability, array destructuring in the loop expression itself is the slowest, it actually performs on the level of forEach:

for (let [key, value] of testMap) ...

Using local variables is half-way between the two, faster than array destructuring but slower than the raw loop:

for (let entry of testMap) {
    let key = entry[0];
    let value = entry[1];
}

Additionally, for-of loops also have the added benefit of not requiring the creation of a function, which means less potential garbage generated when the forEach is called with an anonymous function expression created with each call.

Did a little benchmark with the following code on node.js 8.11

const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();

suite
  .add('for of', function () {
    const m = new Map();
    for (let i = 0; i < 100; i++) {
      m.set(`key${i}`, i);
    }

    for (let v of m) {
      m.delete(v);
    }
  })
  .add('forEach', function () {
    const m = new Map();
    for (let i = 0; i < 100; i++) {
      m.set(`key${i}`, i);
    }

    m.forEach(v => {
      m.delete(v);
    })
  })
  .on('cycle', function (event) {
    console.log(String(event.target));
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  })
  // run async
  .run({ 'async': true });

And the result was pretty interesting:

for of x 88,105 ops/sec ±0.36% (89 runs sampled)
forEach x 81,532 ops/sec ±0.55% (90 runs sampled)
Fastest is for of

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM