PHP8.1がリリースされてそろそろ1年。PHP8.1のRelease Announcementを今更じっくりと眺めていたところ、見逃していた変更点を発見。
Array unpacking support for string-keyed arrays
https://www.php.net/releases/8.1/en.php
配列アンパックが連想配列をサポートするようになった、とのこと。
配列アンパックとは、一般的にいう『スプレッド演算子』『スプレッド構文』のことです。
$x = ['a' => 1, 'b' => 2];
$y = ['c' => 3, 'd' => 4];
$result = [...$x, ...$y];
// ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]
これによって、array_mergeを完全にアンパックに置き換える事が可能になった、ということになりそう。
もうarray_mergeを使うこともなくなるかな、と思いつつ、念のためパフォーマンスを比較してみることに。
検証
// 1000個ほどの要素をもつ連想配列を2つ用意する
$str = join([...range(0, 9), ...range('a', 'z'), ...range('A', 'Z')]);
$arr1 = $arr2 = [];
for ($i = 0; $i < 1000; ++$i) {
$arr1[str_shuffle($str)] = $i;
$arr2[str_shuffle($str)] = $i;
}
// array_mergeを1万回実行するのに要した時間
$start = microtime(true);
for ($i = 0; $i < 10000; ++$i) {
$tmp = array_merge($arr1, $arr2);
}
echo 'array_merge:' . (microtime(true) - $start) . "\n";
// アンパックを1万回実行するのに要した時間
$start = microtime(true);
for ($i = 0; $i < 10000; ++$i) {
$tmp = [...$arr1, ...$arr2];
}
echo 'unpacking:' . (microtime(true) - $start) . "\n";
array_merge | unpacking | |
---|---|---|
1st | 0.606 | 1.031 |
2nd | 0.626 | 1.044 |
3rd | 0.620 | 1.076 |
4th | 0.613 | 1.046 |
5th | 0.621 | 1.039 |
一般的には関数より構文のほうが処理速度が速いといわれていますが、意外な結果になりました。
どうしても納得できず・・・
2つの配列の要素数を100に減らしてみましたが、array_mergeの圧勝。
2つの配列を添字配列にしてみましたが、array_mergeの圧勝。
結合する配列数を増やしてみましたが、array_mergeの圧勝。
せめてメモリ使用量はアンパックに軍配が上がって欲しい・・・と
memory_get_peak_usageを仕込んでみましたが、array_mergeのほうがやや優れていました。
結局どっちを使えばいいの?
他にもいくつかのパターンを比較してみましたが、
すべてではないにしろ、パフォーマンスの面ではarray_mergeのほうが優れているという結果になりました。
特にパフォーマンスが重要な場面ではarray_mergeを使う選択肢はありそうですが、
この程度のパフォーマンス差であれば、どちらかにこだわる必要もないかなと。
個人的にはアンパックを積極的に使っていこうと思います。
ご指摘・ご意見などありましたら、ぜひコメントお願いします。