at posts/single.html

PHP の素朴な疑問とか

PHPを良く知らない人がPHPを語るときは気をつけたほうがいいかもしれない - ito.tetsunosuke/notebookより。

for($i=0; $i < count($array); $i++) { ... }

みたいなコードはどうにかならんのかね。こういう入門書が多くてガチで困る。

$cnt = count($array);
for($i=0; $i < $cnt; $i++) { ... }

を推奨。

C の場合はコンパイラが前者のコードを後者のコードに最適化するって何かで読んだ気がする…けど覚えてない。

ついでなので、 foreach を使う版も試してみた。 これもどこかで読んだ記憶があるけど、インデックスにアクセスするよりも直接変数を参照した方が早いという。 C の本だったか、 Perl の本だったか…。 PHP だったら foreach だね。 個人的には for と $i を使う機会は少ないなぁ。2つの配列を同時に回すときくらい?

foreach ($item as $array) { ... }

気になったのでベンチマークとって比較してみた。 結果は以下の通り。 foreach が一番速い (19.61%) けど count を毎回呼ぶかどうかほどの違い (55.94% と 24.36%) はなかった。 フツーに使う場合はどっちを foreach でも for でもそんなに影響ないかも。

--------------------------------------------------------------------------
marker                        time index            ex time         perct
--------------------------------------------------------------------------
Start                         1197579015.04900200   -                0.00%
--------------------------------------------------------------------------
use count() every time        1197579015.27005700   0.221055        55.94%
--------------------------------------------------------------------------
use count() only first time   1197579015.36633500   0.096278        24.36%
--------------------------------------------------------------------------
use foreach                   1197579015.44383600   0.077501        19.61%
--------------------------------------------------------------------------
Stop                          1197579015.44416700   0.000331         0.08%
--------------------------------------------------------------------------
total                         -                     0.395165       100.00%
--------------------------------------------------------------------------

PHP5.2.1 (cli) を VMware 上で動作させた。 サンプルコードは以下の通り。

<?php
require_once('Benchmark/Timer.php');

$sum = 0;
$array = array();
for ($i = 0; $i < 100000; $i++) {
  $array[$i] = $i;
}
$timer = new Benchmark_Timer(TRUE);

// 毎回 count() を呼び出す
$sum = 0;
for ($i = 0; $i < count($array); $i++) {
  $sum += $array[$i];
}
$timer->setMarker('use count() every time');

// 初回のみ count() を呼び出す
$sum = 0;
$count = count($array);
for ($i = 0; $i < $count; $i++) {
  $sum += $array[$i];
}
$timer->setMarker('use count() only first time');

// foreach を使う
$sum = 0;
foreach ($array as $item) {
  $sum += $item;
}
$timer->setMarker('use foreach');
$timer->display();

Pear::Benchmark も初めて使ったよ。

$ sudo pear install benchmark

で使えるようになる。

関連する日記