JavaScriptで配列から新しい配列を作る処理の性能比較

配列を処理し、別の新しい配列を作る処理の実装方法の違いによる実行速度の違いをテストしてみました。

JavaScriptで配列から最大値を選択する処理の性能比較」 では、主にfor文と組込みのMath.maxとの比較でした。 今回は、通常のfor文と「forEach, filter, map」を使用して比較を行いました。 「forEach, filter, map」などはECMAScript5, JavaScript1.6で追加された配列処理用のメソッドです。 ちなみにECMAScript5は2009年に正式に採択、JavaScript1.6では2005年に追加されました。

登場したての頃はサポートしていないブラウザもありましたが、 現在は少なくともChrome, IE, Firefoxの主要ブラウザではサポートされていますので あまり気にせず使用してもいいかと思います。ただし、IEでのサポートは9からです。 Windows Vista以降なら問題ありませんが、Windows XPのIEのバージョンは6~8なので、 (いまだに)Windows XPやWindows 98, Windows 95をサポートしたいシステムでは使用できません。 気をつけましょう。ちなみにChromeは初期バージョンリリース時から、Firefoxでは1.5からサポートしています。

数値配列から0以上の値の配列を再作成する処理

環境

処理・データ条件

処理種類

※「こちらのページ」で各ソースの確認と、あなたのブラウザを使って実際にテストを実行できます。


左から順に、Chrome, IE, Firefoxでの結果です。



まず全般的に、for文を使った処理が速く、forEachメソッドやfilterメソッドを使った処理では for文を使った処理より大幅に遅いという結果になりました。 その主な原因は、forEach, filterなどのいわゆる「反復メソッド」は、配列の要素数分 引数で与えられたコールバック関数を呼び出すことになるので、そのコストが高いのだと思います。

それと、各ブラウザが高速化競争をしており、ベンチマークテストで高得点を出すために ベンチマークで多用される機能(この中ではfor文)が 優先してチューニングされるという理由もあるかもしれません。

とはいえ、もっとも差のあるFirefoxでも、for文とfilterメソッドを使った処理の差はたかだか25倍程度であり、 多くの場合、他の処理と混じってしまえば違いが判らないほどの差でしか無くなるでしょう。 ですので小さな速度低下はあまり気にせず、人に優しい読みやすいシンプルでエレガントなコードを書くために、 「反復メソッド」を積極的に使用するようにした方がいいと思います。

しかし、非常に大きな配列を何度も繰り返すような処理で、チューニングが必要なほど処理速度が問題になった際には、 このあたりを気にして変更することによって改善するかもしれません。ですので「反復メソッドは少し遅い」 ということを頭の片隅においておきましょう。


ブラウザ間は、ChromeとFirefoxは似た感じで、 for文を使った処理では、IEはChrome, Firefoxの半分程度の速度で、 filterメソッドを使った処理では、IEがFirefoxの4倍程度の速度でした。


ユーザーオブジェクトの配列から
ユーザー名の配列を再作成する処理

処理・データ条件

処理種類

※「こちら」のページで各ソースの確認と、あなたのブラウザを使って実際にテストを実行できます。


左から順に、Chrome, IE, Firefoxでの結果です。

※大文字化処理あり


まずtest03の処理は、書籍「Effective JavaScirpt」の項目60で「すばらしい例」として取り上げられているコードです (書籍では小文字化ですが)。これを読んだときに 『これが「すばらしい例」かよ。反復メソッドを3回も書いたら絶対に遅くなる、普通に書いた方が速いだろ』 と思ったことがきっかけで、この処理速度比較をしてみようと思いました。

全般的に、for文を使った処理が速く、反復メソッドを使った処理では for文を使った処理よりやや遅いという結果になりました。

特にtest03は反復メソッドを3つ使っているので、数値配列の例より遅くなることを期待していたのですが 想像よりも差がつきませんでした。その理由は、ループ以外の処理がやや重いので、 相対的にループの部分の差がつきにくくなっているからです。数値の配列の例と実行回数に着目して比較すると、 こちらの処理は数値の配列の例と比べかなり遅くなっていますことがよくわかります。

処理がやや重い理由は、数値の配列の例はプリミティブな数値が整数かどうかを チェックするだけだったのに対し、こちらはオブジェクトを扱っていることと、 大文字化処理を行っているからです。大文字化処理をはずすとかなり速くなります。

左から順に、Chrome, IE, Firefoxでの結果です。

※大文字化処理なし


ブラウザ間は、「大文字化処理あり」ではChromeとIEは似た感じで、Firefoxが単独でかなり遅いという結果になりました。 「大文字化処理なし」ではfor文の処理のtest01に関しては、ChromeとFirefoxが同じくらいで、IEがやや遅く、 反復メソッドの3連チェーンのtest03はIEがかなり速いという結果になりました。 (ということは「Firfoxの大文字化処理はChrome, IEに比べかなり遅い」ということになりますね…)

こうやって、処理速度を実測していると感じるのですが、現在は主要ブラウザの処理速度は拮抗していて、 処理の種類によって結果が変わるので、どれが速いとは一概には言えないということがよくわかります。


まとめ