次の2つは天と地ほどの違いがあります
- 配列へのforを使ったループ
- 配列へのforEach関数によるループ
速度に違いがあることは分かっています。
そしてforEachの乱用がダメなことも周知です。
でも具体的にどれだけ速度差があるのか…
それを実際に計測してみました。
JSでのforEach乱用を防ぐ戒めでもあります。
このページの目次
ここでの速度計測のやり方と計測方法
次の方法で試してみました。
- あるN個の整数配列を用意する
- その各要素を2倍にするループを回す
- 計測にはperformanceのAPIを使う
JavaScriptにはperformance APIが用意されてます。
それを使うと次のように計測が可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
performance.mark('myPerfStart'); /// 実際に計測したい処理… performance.mark('myPerfEnd'); performance.measure( 'myPerf', 'myPerfStart', 'myPerfEnd' ); const results = performance.getEntriesByName('myPerf'); const time = results[0].duration; console.log( '実行時間 = ' + time + 'ミリ秒' ); |
詳しくは次記事でも解説しました。
▼ JSで処理時間を計測する本当に正しい方法
処理速度の計測には暗黙的にこのAPIを使います
また配列の初期化は計測時間には含まれません。
あくまで要素を2倍するループだけが計測対象です。
1000万要素へのforEachループによる処理時間を計測
次のようなコードで計測してみました。
▼ forEachループで1000万回ループ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/// 配列初期化 const N = 10000000 const intArray = [] for(let i=0; i<N; ++i){ intArray.push(i) } /// 計測開始 /// 各要素を2倍するループ intArray.forEach( (n,i) => { intArray[i] *= 2 }) /// 計測終了 |
1000万個の要素数を持ってる配列
試行回数は5回です。結果は次の通り
1回目 | 136ミリ秒 |
2回目 | 172.5ミリ秒 |
3回目 | 127.2ミリ秒 |
4回目 | 127.1ミリ秒 |
5回目 | 137.7ミリ秒 |
最小が127.1ミリ秒、最長が172.5ミリ秒
1000万要素へのforループによる処理時間を計測
次はforループによる処理速度計測
▼ 1000万回forループしてみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/// 配列初期化 const N = 10000000 const intArray = [] for(let i=0; i<N; ++i){ intArray.push(i) } /// 計測開始 /// 各要素を2倍するループ for(let i=0; i<intArray.length; ++i){ intArray[i] *= 2 } /// 計測終了 |
▼ 5回の試行結果は次の通り
1回目 | 16.4ミリ秒 |
2回目 | 17.5ミリ秒 |
3回目 | 16.1ミリ秒 |
4回目 | 16.8ミリ秒 |
5回目 | 16.7ミリ秒 |
こういう結果に…
圧倒的すぎるほどの差があります
なんと10倍程度も処理速度に差があった!
この結果から分かるのは次のことです
▼ 1000万要素へのループ試行から分かったこと
- forEachの平均速度は127~172ミリ秒
- forループの平均速度は16~17ミリ秒
- 約10倍ほども実行速度に差が出ている
あまりにも大きな差が出ています。
有無を言わさずforループの方が優秀です。
これだけの差がfor vs forEachで出てしまう理由
そもそも forループ と forEach は全く別モノだから
- forは組み込まれている原始的なループ
- forEachは関数による疑似的なループ
関数を呼び出しにはオーバーヘッドがあり、N個の配列だったらN個の関数が呼ばれるから時間がかかるのも当然というわけです。(正確にはJSでの関数は全てFunctionオブジェクト)
一方のforループは当たり前だけどJavaScript命令セットの1つです。原始的なforループだから余計なオーバーヘッドはありません
速度性と利便性はトレードオフということですね
もっともforEachは利便性でも微妙かも…
以上、JSでの forループ vs forEach でした。ではまた