PHPのarray_pushが鼻血出るくらい遅い件
結構な回数ブン回るループを書いていて、ふとarray_pushのマニュアルを読んでみると・・・
「大変遅いから$hoge[$num]で突っ込んだほうが良いよ」
なんてことが書かれている事に気づいた。
あれ? そんな違うの??
いっちょ試すか。
結論からすると、3倍近い差でarray_pushが遅い。
猛烈に遅い!!!
とりあえず以下の様なコードを書いて動かしてみた。
FuelPHP用の記述がなんぼかあるが、意味は伝わるかと。
public function action_apush()
{
$max = 500000;
$a = array();
$b = array();
$c = array();
$t = array();
$pu = "hogefugapiyo";
// array_push
$t[0][0] = microtime(true);
for($i = 0; $i < $max; $i++)
{
array_push($a, $pu);
}
$t[0][1] = microtime(true);
$t[0]['tleft'] = $t[0][1] - $t[0][0];
unset($a); // memory溢れるので
// count direct
$t[1][0] = microtime(true);
for($i = 0; $i < $max; $i++)
{
$b[count($b)] = $pu;
}
$t[1][1] = microtime(true);
$t[1]['tleft'] = $t[1][1] - $t[1][0];
unset($b); // memory溢れるので
// direct
$t[2][0] = microtime(true);
for($i = 0; $i < $max; $i++)
{
$c[$i] = $pu;
}
$t[2][1] = microtime(true);
$t[2]['tleft'] = $t[2][1] - $t[2][0];
//unset($c); // memory溢れるので
// 賢く?
//$c = array(); // ええい面倒だ
$t[3][0] = microtime(true);
$acnt = count($c); // 途中から続行してみよう
for($i = 0; $i < $max; $i++)
{
$c[$acnt + $i] = $pu;
}
$t[3][1] = microtime(true);
$t[3]['tleft'] = $t[3][1] - $t[3][0];
unset($c);
$output_twig = 'common/json.twig';
$data['result'] = $t;
return Response::forge(View::forge($output_twig, $data));
}
んで、実行結果は・・・・
・array_pushで追加した場合(561ms)
{"0":1395989176.1882,"1":1395989176.7498,"tleft":0.56161093711853}
・毎回countして末尾に追加した場合(500ms)
{"0":1395989176.7638,"1":1395989177.2642,"tleft":0.50038194656372}
・0番目から普通に追加していった場合(157ms)
{"0":1395989177.2795,"1":1395989177.4374,"tleft":0.15785098075867}
・最初にcountしてそっからインクリメント値を足して追加していった場合(188ms)
{"0":1395989177.4374,"1":1395989177.6254,"tleft":0.18804693222046}
最後の計測結果は、空のarrayをカウントしてからのスタートだとあまり意味がなさそうなので、3番目の結果作られたArrayの後ろに追加するようにしてみた。
この結果見ると、array_pushはやめとけって結論になるなぁ。
差がでかすぎる。。。
中で何をしていたらこんなに遅くなるんだろう。逆に興味が湧いてきました。
さて、今日はこの辺で。