PHPのarray操作はどれが一番速いか
なになに
あまり有名ではないのでもしかしたらご存じないかもしれませんが、PHPには高速高機能なforeachってイテレーション機構が言語組み込みにあるので、わざわざarray_mapとか書かなくてもいいんですよ!!!!!
— 零崎ぞぬ織 (@tadsan) 2016年5月25日
array_mapに渡していいのはcallableな値のみで、 array_map(function(){ ... とか書き始めたらそれは敗北フラグ。素直に foreach で書け!
— 零崎ぞぬ織 (@tadsan) 2016年5月25日
けど配列のフェッチと新しい配列への格納でPHPオペコード増えるし、組み込み関数のほうが速いんじゃないの?
検証してみた:
> php -d memory_limit=-1 array-spped-test.php Ginq + Closure: 782.2070ms x1.00 Ginq + function: 785.6706ms x1.00 array_map + Closure: 99.5564ms x7.86 array_map + function: 67.2468ms x11.63 foreach with key: 52.4326ms x14.92 foreach without key: 46.9100ms x16.67
array_map と foreach でだいたい2倍差。PHPは配列を操作するオペコード増加ぶんより、関数を呼ぶほうがずっと重いようです。で、関数よりクロージャーのほうがさらに重い。
で、それらに比べて高級なライブラリは、もっと違うオーバーヘッドがかかるので10倍とか変わってくる、と。PSRでコレクションAPIインターフェースの標準化っていう考えは、ちょっとアレですね。そこは性能差が出すぎるから微妙って感じ。
いや、だからって Ginq みたいなのが役立たずかってことはなくて、遅延とかバッチとか yield な感じのイテレーションでは大事ですよ。あと、100件ページに出す程度なら誤差の範囲ですよ。こんだけ高級なのに、100万要素で1秒以内なら、十分じゃないですかね。
ところで、array_map で確実な差が出る関数とクロージャー、Ginqでほとんど違わないのはちょっと不思議です。
ま、とは言っても自分は性能差関係ないとこなら普通に
<?= Hoge::widget([ 'data' => array_map(function($e) use($nanika) { return $nanika->format($e->hogefuga()); }, $rawData), ]) ?>
とかやりますけどね。ただ、foreach より array_map のほうがカッコいいって言っちゃう人の持ち点はこれでひとつ消えたな、と。