条件式の省略化時の速度

mixiの [Let's PHP] トピックで、ある変数が「1」か「2」か「3」か「4」か「5」か「6」の時に何かする場合の条件式の書き方の話が出ていた。そこに、僕は、isset()を使うとちょっと速いという件を書き込んだ。というわけで、ベンチマークをしてみる。

function mtime_diff($a, $b)
{
    list($a_dec, $a_sec) = explode(' ', $a);
    list($b_dec, $b_sec) = explode(' ', $b);
    return $b_sec - $a_sec + $b_dec - $a_dec;
}

$nums = array();
for ($i=0; $i<10000; $i++) {
	$nums[] = mt_rand(1,20);
}

$st = microtime();
$ret = 0;
foreach ($nums as $num) {
	if ($num == 1
	|| $num == 2
	|| $num == 3
	|| $num == 4
	|| $num == 5
	|| $num == 6) {
	    $ret += 1;
	}
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

$st = microtime();
$ret = 0;
foreach ($nums as $num) {
	switch ($num) {
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
		$ret += 1;
	} 
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

$st = microtime();
$chk = array(1,2,3,4,5,6);
$ret = 0;
foreach ($nums as $num) {
	if (in_array($num, $chk)) {
	    $ret += 1;
	}
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

$st = microtime();
$chk2 = array(1 =>1 ,2=>1 ,3=>1 ,4=>1 ,5=>1 ,6=>1 );
$ret = 0;
foreach ($nums as $num) {
	if (isset($chk2[$num])) {
	    $ret += 1;
	}
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

$st = microtime();
$chk3 = array(1 =>1 ,2=>1 ,3=>1 ,4=>1 ,5=>1 ,6=>1 );
$ret = 0;
foreach ($nums as $num) {
	if ($chk3[$num]) {
	    $ret += 1;
	}
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

$st = microtime();
$chk4 = array(1 =>1 ,2=>1 ,3=>1 ,4=>1 ,5=>1 ,6=>1 );
$ret = 0;
foreach ($nums as $num) {
	if (@$chk4[$num]) {
	    $ret += 1;
	}
}
echo sprintf("%0.5f <br>", mtime_diff($st, microtime()));

結果は、自分のセレロン1GHzのwinXP_homeノート(Apache/1.3.31+PHP/4.3.7)では、
0.05237
0.04205
0.04645
0.03138
0.05120
0.09256
となった。
(1)if文べた書きより、(2)switch文および(3)in_array()方式が20%程度速く、(4)isset()方式がもっとも速く40%ほど向上。(5)選択肢の配列をそのまま書く方式は意外にも(1)if文べた書きと同程度で、念のため(6)noticeが出ないように@をつけると倍近く遅くなる。

追記:書き忘れてたけど、僕の環境ではerror_reporting(E_ALL ^ E_NOTICE)でnoticeは表示されない設定。