for文の作法

作法とまで言うと大袈裟だけど、実行速度の話。仕事の息抜きに実験した。
確かにいつからか疑問には思っていたけど、具体的に計測したこと無かったっていうのと、そこまで大規模な処理を行ったことが無くて気にしてなかった。

何が疑問かって、for文書く時に

<?php
for($i = 0; $i < sizeof($num); $i ++){
}
?>

という風に、継続条件でsizeofとか計算しちゃうのは正直どうなの?っていう。
多分まともに勉強なさってる人は多分こんな書き方しなくて、

<?php
for($i = 0, $len = $num; $i < $len; $i ++){
}
?>

とかいうふうに書くと思うんですよ。

実際、恥ずかしい話ですが結構最近まで一番上の書き方をしてました。
ある日、急に気になってとある人に相談したところ、やっぱり『for文の継続条件内で計算とかしたら毎回処理が行われるから遅くなるに決まってる』と言われて、そりゃそうだよなと思ったわけです。それ以来書き方を変えてやってるんですが、実際どれだけ違うのか単純なテストをしてみました。

PHPの実行速度を計測する方法 - 香川でホームページ制作
http://blog.aulta.net/2008/08/14/utilityphp-php%E3%81%AE%E5%AE%9F%E8%A1%8C%E9%80%9F%E5%BA%A6%E3%82%92%E8%A8%88%E6%B8%AC%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

↑のサイトの計測方法を参考にしてます。
普段Cakeばかりなので、しょっちゅう配列地獄ということでsizeof()を使います。
とりあえず何も処理はさせずに100万回ループさせてみます。

<?php
define('C_DECIMALS', 7);
function getMicrotime(){
	list($msec, $sec) = explode(" ", microtime());
	return ((float)$sec + (float)$msec);
}
//配列を作る
$num = 1000000;
$array = array();
for($i=0;$i<$num;$i++){
	$array[] = 1;
}

//sizeofをforの中へ
$startTime = getMicrotime();
for($i=1;$i<sizeof($array);$i++){}
$endTime = getMicrotime();

echo number_format($endTime - $startTime, C_DECIMALS) . '<hr />';

//$lenは予め設定(forの中)
$startTime = getMicrotime();
for($i=1,$len=sizeof($array);$i<$len;$i++){}
$endTime = getMicrotime();

echo number_format($endTime - $startTime, C_DECIMALS) . '<hr />';

//$lenは予め設定(forの外)
$len=sizeof($array);

$startTime = getMicrotime();
for($i=1;$i<$len;$i++){}
$endTime = getMicrotime();

echo number_format($endTime - $startTime, C_DECIMALS) . '<hr />';
?>

とりあえず結果がわかれば。
会社のPCだと上から順番に、大体平均して
0.3223
0.0755
0.0755
という結果が出ました。
初期化部分は初めの一回しか処理を行わないので、下2つの処理速度はあまり変わらず。

フィーリングプログラマ(笑)なのであまりこういう考察はしないんですが、
たまには真面目に勉強しないと無駄なリソース食うクッキーモンスターになってしまいそうです。


というわけでfor文書く時に一番上の書き方でやっちゃってる人は変えたほうがいいです。sizeof()とかcount()する場合は初期化部分に書くように。