which statement is faster, elseif() or switch() ?

A couple of days ago I was out on a run and I starting wondering which statement was faster, a elseif() or a switch().  I am a big fan of switch statements.  I like how clean they look and its really easy to add a new condition to them.  I also assumed that they were much quicker than elseif statements.  So I set up this test to try to prove to myself that I was right.

Here is the script that I used to test my theory. You can download this script and the script timer here.  How it works its we have 3 loops. In the first loop we pick a value randomly out of our test data array.  Then we loop through each statement type(switch and elseif) the value of timing_loops. While doing that we record the length of time it takes to compare the values.  Then we record the tested values from our test data array and the method that was faster by how many microseconds.  Its a pretty simple script, and my no means the best I have written.

 

 * @author Jesse Baird <jebaird@gmail.com>
 * @since 12/1/2008
 */

require 'PHP_script_timer.php';

$test = array();

$test[0] = 'cat';
$test[1] = 'dog';
$test[2] = 'frog';
$test[3] = 'goat';
$test[4] = 'pig';
$test[5] = 'sometingreallylong';
$test[6] = time(); //this one will be used for an else/default

define('timing_loops',1000);
$times_to_run=30;
$valsTested=array();
$fhandle= fopen('elseif_vs_switch_benchmark.log','a'); 

for($i=0;$i<$times_to_run;$i++){
$timing=array();

//get the val to test on this loop
$tval = $test[rand(0, 6)];
$valsTested[$i]=$tval;
for ($current_loop = 0; $current_loop < timing_loops; $current_loop++) {


$time_start = microtime_float();
switch($tval) {
    case 'cat':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    case 'dog':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    case 'frog':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    case 'goat':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    case 'pig':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    case 'sometingreallylong':
		$switch_endVal=time()+rand(0,10000000000);
        break;
    default:
		$switch_endVal=time()+rand(0,10000000000);
        break;


}
$timing[] = microtime_float() - $time_start;
}
echo '<b>switch</b><br>';
$switchAve= timing($timing);



$timing=array();

for ($current_loop2 = 0; $current_loop2 < timing_loops; $current_loop2++) {


$time_start = microtime_float();

if($tval == 'cat') {
$elseif_endVal=time()+rand(0,10000000000);
} elseif($tval == 'dog') {
$elseif_endVal=time()+rand(0,10000000000);
} elseif($tval == 'frog') {
$elseif_endVal=time()+rand(0,10000000000);
} elseif($tval == 'goat') {
$elseif_endVal=time()+rand(0,10000000000);
} elseif($tval == 'pig') {
$elseif_endVal=time()+rand(0,10000000000);
} elseif($tval == 'sometingreallylong') {
$elseif_endVal=time()+rand(0,10000000000);
} else {
$elseif_endVal=time()+rand(0,10000000000);
}
$timing[] = microtime_float() - $time_start;
}
echo '<b>else if</b><br>';
$elseIFAve= timing($timing);

//you can use this level if loging if you like

//ob_start();
//echo 'tested val: '.$tval."rn";
////echo $elseIFAve;
//if((float)$elseIFAve>(float)$switchAve)
//printf("switch method average %f mirco secs faster",((float)$elseIFAve-(float)$switchAve));
////echo 'switch method average '.($elseIFAve-$switchAve).' mirco secs faster';
//else
//printf("elseif method average %f mirco secs faster",((float)$switchAve-(float)$elseIFAve));
//echo "rnrn";
//$buffer=ob_get_contents();
//fwrite($fhandle,$buffer,strlen($buffer));
//ob_end_flush();
////echo 'elseif method average '.($switchAve-$elseIFAve).' mirco secs faster';

$switchTotalAve+=(float)$switchAve;
$elseIFTotalAve+=(float)$elseIFAve;
}
//add some info the the log
ob_start();
echo 'ran '.$times_to_run." timesrn tested values:rn".var_export($valsTested)."rn";
//echo $elseIFAve;
if((float)$elseIFTotalAve>(float)$switchTotalAve)
printf("switch method average %f mirco secs faster",((float)$elseIFTotalAve-(float)$switchTotalAve));
//echo 'switch method average '.($elseIFAve-$switchAve).' mirco secs faster';
else
printf("elseif method average %f mirco secs faster",((float)$switchTotalAve-(float)$elseIFTotalAve));
echo "rnrn";
$buffer=ob_get_contents();
fwrite($fhandle,$buffer,strlen($buffer));
ob_end_flush();
//printf("switch method average %f mirco secs faster",($elseIFAve-$switchAve));

?>

I ran the test script 18 times.  The switch statement was faster 9 times v.s. 8 for the elseif.  Here is a quick break down of the data and somethings that I noticed while testing/writing this script.

  • The sum of the total time taken by the switch statement was: 0.000402 microseconds
  • The sum of the total time taken by the elseif statement was: 0.000628 microseconds
  • The elseif compared values quicker if the value was close to the top of the statement.  While the switch seemed to test all values at the same speed. Thus it might make sense to use an elseif if you know the possible value that is going to be used the most. I.E. if your going to be using the 'cat' statement.

 Looking that the data trends it appears that the switch is the better statement to use if one value is not favored over an another.  I'm still going to stick with my switch statements.  I highly suggest that you run this test your self and see what you come up with.  Change the values, use math computations, etc, its all a matter a preference.