🚄

JavaScript の Array.some と Array.includes と Array.everyの実行速度比較

2022/06/12に公開

本記事の目的

JavaScriptで配列の中に特定の要素が含まれているかを判定する関数の代表格であるArray.some()、Array.includes()、Array.every()。
これらの処理にかかる時間が気になったのでコード書いて試してみた。

今回は実行速度に注目しているので、基本的な情報や細かな仕様は別記事を参考にしてほしい。

ドキュメントリンク
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
https://qiita.com/Nossa/items/4a425e57ec4b7eedb7cb

計測コード

計測コードは以下の通り

performance.js
const { performance } = require('perf_hooks');

const calcTime = (func, name) => {
  const numberOfTests = 100
  const startTime = performance.now(); // 開始時間
  for (  let i = 0;  i < numberOfTests;  i++  ) {
    func()
  }
  const endTime = performance.now(); // 終了時間
  const funcTime = ( endTime - startTime ) / numberOfTests
  console.log(`${name}の作動時間は平均${funcTime}ミリ秒`)
}

const millionArray = [...Array(1000000).keys()]

const someFuncFirst = () => {
  millionArray.some(e => e >= 0)
}

const someFuncEnd = () => {
  millionArray.some(e => e >= 1000000 - 1)
}

const everyFuncFirstNotOk = () => {
  millionArray.every(e => e > 0)
}

const everyFuncAllOk = () => {
  millionArray.every(e => e >= 0)
}

const includesFuncStart = () => {
  millionArray.includes(0)
}

const includesFuncEnd = () => {
  millionArray.includes(1000000 - 1)
}



calcTime(someFuncFirst, 'some関数で最初に条件ヒット')
calcTime(someFuncEnd, 'some関数で最後に条件ヒット')
calcTime(everyFuncFirstNotOk, 'every関数で最初に条件を満たさない')
calcTime(everyFuncAllOk, 'every関数で全て条件ヒット')
calcTime(includesFuncStart, 'includes関数で最初に条件ヒット')
calcTime(includesFuncEnd, 'includes関数で最後に条件ヒット')

関数を100回実行してかかった時間をperformance関数で取得し、平均を求める。

テスト内容

試したのは以下の6パターン

  • some関数で1回目に条件を満たすパターン
  • some関数で1000000回目に条件を満たすパターン
  • every関数で1回目に条件を満たさないパターン
  • every関数で1000000回全て条件を満たすパターン
  • includes関数で1回目に条件を満たすパターン
  • includes関数で1000000回目に条件を満たすパターン

実際にやってみた

コード実行

$ node perforamnce.js 
some関数で最初に条件ヒットの作動時間は平均0.008239719867706299ミリ秒
some関数で最後に条件ヒットの作動時間は平均16.483924310207367ミリ秒
every関数で最初に条件を満たさないの作動時間は平均0.0017472004890441894ミリ秒
every関数で全て条件ヒットの作動時間は平均17.569544270038605ミリ秒
includes関数で最初に条件ヒットの作動時間は平均0.0010861003398895265ミリ秒
includes関数で最後に条件ヒットの作動時間は平均1.4430855703353882ミリ秒

発見

大体想定通りであった。
(計測時間的に明らかであるが、億が一別の理由もあるかも?)

Array.some()

初めに条件を満たす要素を見つけたら、それ以降は処理を行なっていない。

Array.every()

初めに条件を満たさない要素を見つけたら、それ以降は処理を行なっていない。

Array.includes()

初めに条件を満たす要素を見つけたら、それ以降は処理を行なっていない。

some()とincludes()の違い

some()の方がincludes()よりも10倍前後時間がかかっていた。
これはincludes()は要素との一致なのに、対してsome()は比較だからだと思う。

試しに、someの条件を比較(>=)ではなく一致(===)に変更して再度処理を実行してみた。

performance.js
/* 略 */
const someFuncFirst = () => {
  millionArray.some(e => e === 0)
}

const someFuncEnd = () => {
  millionArray.some(e => e === 1000000 - 1)
}
/* 略 */

その結果は、

$ node perforamnce.js 
some関数で最初に条件ヒットの作動時間は平均0.011782319545745849ミリ秒
some関数で最後に条件ヒットの作動時間は平均16.23324474096298ミリ秒
includes関数で最初に条件ヒットの作動時間は平均0.0008628797531127929ミリ秒
includes関数で最後に条件ヒットの作動時間は平均2.4398624300956726ミリ秒

これでも10倍前後の差があった。

一致する要素があるか判定するだけであれば、includesの方が10倍程度処理が早くなるらしい。

Discussion