PHP 7系からは高速array_diff関数は必要ない
2016-11-18
PHP 5.6以前では、遅かった配列処理系の関数も、PHP 7以降ではかなり高速化されています。
PHP 5.6以前で、array_diff関数が遅く、独自の高速化array_diff関数を使っていた方も多いのではないでしょうか。
以下のような関数です。
高速化array_diff関数
<?php
function fast_array_diff()
{
return array_flip(call_user_func_array('array_diff_key', array_map('array_flip', func_get_args())));
}
上記のfast_array_diff
関数は、$array === array_flip(array_flip($array))
が成立するような配列にのみ適用できる、array_diffを高速化した関数です。つまり、以下の場合のみ利用することができます。
- 配列の全ての要素が「整数(int)」or「10進数値形式ではない文字列(string)」からなる
- 配列の全ての要素がユニークである(重複しない)
上記は、array_flip関数を用いているがための特性です。
PHP 5.6以前では、この条件下であれば、これを用いてarray_diff関数をかなり高速化することができました。
ベンチマーク
実際に、こちらのプログラムを用いて、ベンチマークを行ってみます。
ランダムに並び替えられた15万の要素(厳密には150,001要素だが、以下省略)を持つ配列と、ランダムに並び替えられた10万の要素を持つ配列で、array_diff関数を実行し、時間を計測するプログラムです。
array_diff.php
は通常のarray_diff関数を、fast_array_diff.php
は独自の高速化array_diff関数fast_array_diff()
を利用します。
PHP 5.6
PHP 5.6環境における結果が、以下のとおりです。
$ php -v
PHP 5.6.25 (cli) (built: Sep 6 2016 16:37:16)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 1.0187411308289秒
$ php fast_array_diff.php
処理時間: 0.1289598941803秒
array_diff.php
は処理に1秒以上かかっており、fast_array_diff.php
の方がかなり早く処理できることがわかると思います。
PHP 7.0
ところが、PHP 7.0における結果は、以下のようになります。
$ php -v
PHP 7.0.12 (cli) (built: Oct 14 2016 09:56:59) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 0.039209127426147秒
$ php fast_array_diff.php
処理時間: 0.033622026443481秒
そもそもの処理時間が5.6に比べ、かなり短くなっていることに加え、若干fast_array_diff.php
の方が早いですが、両者の処理時間の差はほとんど誤差のレベルまで縮んでいます。
ここまで処理時間の差が縮んでしまえば、fast_array_diff
関数が特定の条件下でしか利用できないデメリットを考えると、もうほとんどのケースにおいてfast_array_diff
関数は利用しなくてもよいと考えて問題ないでしょう。
引数3つ時のベンチマーク
念のため、引数が3つの場合のベンチマークも行っておきます。
実行するプログラムは、こちらです。
ランダムに並び替えられた15万の要素を持つ配列と、ランダムに並び替えられた10万の要素を持つ配列2つで、array_diff関数を実行し、時間を計測するプログラムです。
PHP 5.6
PHP 5.6環境における結果は、以下のとおりです。
$ php -v
PHP 5.6.25 (cli) (built: Sep 6 2016 16:37:16)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 1.4854810237885秒
$ php fast_array_diff.php
処理時間: 0.17208290100098秒
1回目と同様、fast_array_diff.php
の方がかなり早いです。
PHP 7.0
PHP 7.0における結果は、以下のとおりです。
$ php -v
PHP 7.0.12 (cli) (built: Oct 14 2016 09:56:59) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 0.059709787368774秒
$ php fast_array_diff.php
処理時間: 0.034765005111694秒
引数を3つにすると、2つのときよりも処理時間の差が開きました。ここにきて盛り返すfast_array_diff.php
。
しかし、十数万単位の配列操作で0.03秒程度の差であれば、やはりPHP 7.0においてfast_array_diff
関数を採用するメリットは少なそうです。
引数5つ時のベンチマーク
引数3つでPHP 7.0の処理時間の差が開いてしまったので、念のため、5つでもベンチマーク。
例によって、実行するプログラムは、こちらです。
PHP 5.6
PHP 5.6環境における結果は、以下のとおりです。
$ php -v
PHP 5.6.25 (cli) (built: Sep 6 2016 16:37:16)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 2.1798341274261秒
$ php fast_array_diff.php
処理時間: 0.20542788505554秒
これまでと同様にfast_array_diff.php
の方がかなり早いです。こちらもPHP 7.0と同様に、だんだんと処理時間に差が開いてきました。
PHP 7.0
PHP 7.0における結果は、以下のとおりです。
$ php -v
PHP 7.0.12 (cli) (built: Oct 14 2016 09:56:59) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
$ php array_diff.php
処理時間: 0.097110986709595秒
$ php fast_array_diff.php
処理時間: 0.03524112701416秒
またも、差が開きました。
fast_array_diff.php
に関していえば、引数が増えても処理速度が全然増えません。データ量にあまり依存しないのは、この関数のメリットでしょうか。
まとめ
PHP 7以降の環境では、一般的な用途では、高速化array_diff関数は必要ないです。
しかしながら、配列処理の遅延が命取りになるような環境でなおかつ、array_diff()
に大量に引数を与えるような利用をする場合は、利用するのもアリです。
普通は、もう利用しなくていいでしょう。
まだ、PHP 5系で頑張っている方々は、7系の導入を検討してみてはいかがでしょうか。