"if" versus "switch"

I know, micro-optimization is bad. But curious as I am, I did a little benchmark using this script:

<?php
$numof = 100000;
$file = fopen('benchmark.php', 'w');
if (!$file) die('file error');
fwrite($file, '<pre><?php' . "\n" . 'echo $i = $_GET[\'i\'], "\n";' . "\n");

fwrite($file,
'$start = microtime(true);
if ($i == 0) {}' . "\n");
for ($i = 1; $i < $numof; ++$i) {
    fwrite($file, 'elseif($i == '.$i.') {}'. "\n");
}
fwrite($file,
'echo \'elseif took: \', microtime(true) - $start, "\n";' . "\n");

fwrite($file,
'$start = microtime(true);
switch($i) {' . "\n");
for ($i = 1; $i < $numof; ++$i) {
    fwrite($file, 'case '.$i.': break;'. "\n");
}
fwrite($file,
'}
echo \'switch took: \', microtime(true) - $start, "\n";' . "\n");

Resulting data (for numof = 100000):

i: 0
elseif took: 6.2942504882812E-5
switch took: 3.504753112793E-5

i: 10
elseif took: 6.4849853515625E-5
switch took: 4.3869018554688E-5

i: 100
elseif took: 0.00014805793762207
switch took: 0.00011801719665527

i: 1000
elseif took: 0.00069785118103027
switch took: 0.00098896026611328

i: 10000
elseif took: 0.0059938430786133
switch took: 0.0074150562286377

i: 100000 (first non-existing offset)
elseif took: 0.043318033218384
switch took: 0.075783014297485

I have run the script on my old and slow windows machine with PHP 5.3.1 or 5.3.2, I don't know right know.


Personally, I find the switch a lot more readable. Here's the reason:

if ($foo == 'bar') {
} elseif ($foo == 'baz') {
} elseif ($foo == 'buz') {
} elseif ($fou == 'haz') {
}

Condensed like that, you can easily see the trip up (be it a typo, or a honest difference). But with a switch, you know implicitly what was meant:

switch ($foo) {
    case 'bar': 
        break;
    case 'baz': 
        break;
    case 'buz': 
        break;
    case 'haz': 
        break;
}

Plus, which is easier to read:

if ($foo == 'bar' || $foo == 'baz' || $foo == 'bat' || $foo == 'buz') {
}

or

case 'bar':
case 'baz':
case 'bat':
case 'buz':
    break;

From a performance standpoint... Well, don't worry about the performance. Unless you're doing a few thousand of them inside of a tight loop, you won't even be able to tell the difference (the difference will likely be in the micro-second range, if not lower).

Go for the method that you find the most readable. That's the important part. Don't try to micro-optimize. Remember, Premature Optimization Is The Root Of All Evil...


You should consider using polymorphism as an alternative to control structures like if or switch. It's especially convenient if you have very many options, as it can simplify the control logic a lot.

I wrote about the concept here: http://codeutopia.net/blog/2009/02/02/avoiding-endless-switch-case-structures-with-classes/