【JavaScript】連想配列(Map)のループ処理はforEachの方が性能が良かった件

「forEachは可読性高いけど性能は低い」みたいな印象を持っていたのですが、測定してみたらそんなことありませんでした、っていうタイトル通りのお話です。

測定結果

5回ほど測定してみましたが、forEachが1.7倍ほど高速という結果になりました。

for…of文forEach文
1回目33.415.7
2回目22.015.5
3回目24.014.7
4回目24.514.3
5回目21.914.6
平均25.215.0
※単位はミリ秒

測定に使用したコード

const COUNT_MAX = 1000000;

console.log('elapsedTime1[ms],elapsedTime2[ms]');

for(let i = 0; i < 5; i++) {
    measurement();
}

function measurement() {
    let myMap = new Map();
    for(let i = 0; i < COUNT_MAX; i++) {
        let num = String(i).padStart(8, '0');
        myMap.set('key' + num, 'val' + num);
    }
    // 同じオブジェクト使うと最適化されて後が速くなるとかありそうなので別オブジェクトで定義しておく
    let myMap2 = new Map();
    for(let i = 0; i < COUNT_MAX; i++) {
        let num = String(i).padStart(8, '0');
        myMap2.set('key' + num, 'val' + num);
    }

    // forEach文
    const startTime1 = performance.now();
    myMap.forEach((value, key) => {
        // 参照しない場合は最適化されて参照時と性能が全然違うとかありそうなので念の為参照だけしておく
        if (key == value) {
            // 特に意味のない処理(デッドルート)
            console.log(`key=${key}, value=${value}`);
        }
    });
    const elapsedTime1 = performance.now() - startTime1;

    // for...of文
    const startTime2 = performance.now();
    for (const [key, value] of myMap2.entries()) {
        // 参照しない場合は最適化されて参照時と性能が全然違うとかありそうなので念の為参照だけしておく
        if (key == value) {
            // 特に意味のない処理(デッドルート)
            console.log(`key=${key}, value=${value}`);
        }
    }
    const elapsedTime2 = performance.now() - startTime2;

    console.log(`${elapsedTime1},${elapsedTime2}`)
}

参考

繰り返し処理について
https://qiita.com/think49/items/0c5ea1c9e2545fa2eed2
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Loops_and_iteration
https://stackoverflow.com/questions/49809601/best-practice-javascript-for-loop

性能測定について
https://sbfl.net/blog/2017/12/01/javascript-measure-time/

コメント

タイトルとURLをコピーしました