プロファイラで調べてみたところ、
巨大な配列を array_shift() でループしてるところでかなり時間がかかっていました。
今まで気づかなかったのがアホなのですが、、
ためしに
$row = array_shift($rows); // (処理) $new_row[] = $row;としていたのを
$row = $rows[$i++]; // (処理) $new_row[] = $row;に変えてみたら、ビックリするくらい速くなりました。
でも これではメモリがどんどん食われていきます。
そこで、
以下のようにシフトする代わりに null で埋めていく処理にしてみました。
$row = $rows[$i]; $rows[$i] = null; $i++; // (処理) $new_row[] = $row;結果として、array_shift() とメモリコストはほぼ同じで高速化できました。
そんなに違うの?と疑問かと思うのでベンチマークとってみました。
<?php
// 配列を作成
$array = array();
// ベンチマークタイマー読み込み
require_once 'Benchmark/Timer.php';
$bench = new Benchmark_Timer;
$bench->start();
// -------------- array_shift --------------
// 10000 のアイテムを持つ連想配列を作成
for ($i = 0; $i < 10000; $i++) {
$array[] = array('key' => 'value' . $i);
}
// array_shift() で空になるまでシフト
while (--$i >= 0) {
$shift = array_shift($array);
}
$bench->setMarker('array_shift');
// --------------- null fill ---------------
// 同じく 10000 の連想配列を作成
for ($i = 0; $i < 10000; $i++) {
$array[] = array('key' => 'value' . $i);
}
// array_shift() の代わりに null で埋める
$j = 0;
while (--$i >= 0) {
$shift = $array[$j];
$array[$j] = null;
$j++;
}
// 結果的に同じになるよう初期化
$array = array();
$bench->setMarker('null fill');
// -----------------------------------------
$bench->stop();
$bench->display();
?>
結果:
| time index | ex time | % | |
| Start | 1269384227.24003700 | - | 0.00% |
| array_shift | 1269384227.95581800 | 0.715781 | 97.70% |
| null fill | 1269384227.97259900 | 0.016781 | 2.29% |
| Stop | 1269384227.97264300 | 0.000044 | 0.01% |
| total | - | 0.732606 | 100.00% |
10000 ループだけでもここまで違いがわかります。
圧倒的に null で埋めるほうが速い
もっと早く気付けばよかった。。

0 コメント:
コメントを投稿