PHP7から、キーが0から始まる連番のarrayについて、内部的には連続したメモリ領域を使う純粋配列となり、パフォーマンスが大幅に向上しました。
一方、SplFixedArrayという、高速・省メモリが売りの固定長の純粋配列クラスがPHP5.3の頃からあります。
PHP7になって、SplFixedArrayのarrayに対する強みがどうなったのか、検証してみました。
#検証内容
arrayとSplFixedArrayそれぞれで、100万件のintをセット、ゲット、foreachで回し、速度とメモリ使用量を確かめました。
#前提条件
- 仮想マシン(VMware Player)
- CPU 1コア
- メモリ 1GB
- OS CentOS 7.1
- PHP v7.0.10
- CLIで実行
#検証コード
##array
$num = 1000000;
$array = [];
$start = microtime(true);
for($i = 0; $i < $num; ++$i) {
$array[$i] = $i;
}
$addTime = microtime(true) - $start;
$memoryPeakUsage = memory_get_peak_usage(false);
$memoryPeakUsageReal = memory_get_peak_usage(true);
$start = microtime(true);
for($i = 0; $i < $num; ++$i) {
$array[$i];
}
$getTime = microtime(true) - $start;
$start = microtime(true);
foreach($array as $i) {
}
$foreachTime = microtime(true) - $start;
##SplFixedArray
$num = 1000000;
$array = new SplFixedArray($num);
$start = microtime(true);
for($i = 0; $i < $num; ++$i) {
$array[$i] = $i;
}
$addTime = microtime(true) - $start;
$memoryPeakUsage = memory_get_peak_usage(false);
$memoryPeakUsageReal = memory_get_peak_usage(true);
$start = microtime(true);
for($i = 0; $i < $num; ++$i) {
$array[$i];
}
$getTime = microtime(true) - $start;
$start = microtime(true);
foreach($array as $i) {
}
$foreachTime = microtime(true) - $start;
#結果
10回試行し、最大値と最小値を除く8つのデータの平均値で算出。
array | SplFixedArray | |
---|---|---|
データのセット(秒) | 0.043141692876816 | 0.034425288438797 |
データのゲット(秒) | 0.02352038025856 | 0.030383437871933 |
foreach(秒) | 0.011791378259659 | 0.029610127210617 |
メモリ(Byte) | 33912008 | 16356568 |
リアルメモリ(Byte) | 35655680 | 18100224 |
#考察
データのセットはSplFixedArrayに、データのゲットはarrayに軍配があがりました。
興味深いのはforeachで、3倍弱ほどarrayが速くなっています。
メモリ上の連続領域に格納されているデータに、シーケンシャルにアクセスするのが速いのはわかりますが、SplFixedArrayはどんなデータ構造なのか。おそらくCで書かれていると思うので、ソースコードを見れば何かわかりそう。
メモリは2倍ほどSplFixedArrayがコストが安いです。これはさすがといったところ。
Readが多いデータはarrayで、Writeも入るデータやメモリに関して制約が厳しい場合はSplFixedArrayで、といったところでしょうか。
ただし、SplFixedArrayはオブジェクト生成のコストも考慮する必要があります。