views:

417

answers:

2

I'm looking at trying to optimise a particular function in a php app and foolishly assumed that a boolean lookup in a 'if' statement would be quicker than a string compare. But to check it I put together a short test (see below). To my surprise, the string lookup was quicker.

Is there anything wrong with my test (I'm wired on too much coffee so I'm suspicious of my own code)? If not, I would be interested in any comments people have around string versus boolean lookups in php.

The result for the first test (boolean lookup) was 0.168

The result for the second test (string lookup) was 0.005

<?php

$how_many = 1000000;
$counter1 = 0;
$counter2 = 0;

$abc = array('boolean_lookup'=>TRUE, 'string_lookup'=>'something_else');

$start = microtime();
for($i = 0; $i < $how_many; $i++)
{
    if($abc['boolean_lookup'])
    {
     $counter1++;
    }

}

echo ($start - microtime());

echo '<hr>';


$start = microtime();
for($i = 0; $i < $how_many; $i++)
{
    if($abc['string_lookup'] == 'something_else')
    {
     $counter2++;
    }

}

echo ($start - microtime());
+4  A: 

Yes, you've had too much coffee. You need to use microtime(true) otherwise your date calculations are working on the milliseconds but completely ignoring seconds. Also, use current time - start time to measure duration, not start time - current time, or else you get a negative time. Try the following code instead:

<?php

$how_many = 5000000;
$counter1 = 0;
$counter2 = 0;

$abc = array('boolean_lookup'=>TRUE, 'string_lookup'=>'something_else');

$start = microtime(true);
for($i = 0; $i < $how_many; $i++)
{
    if($abc['boolean_lookup'])
    {
        $counter1++;
    }

}

echo "FIRST: ", (microtime(true) - $start), "\n";

$start = microtime(true);
for($i = 0; $i < $how_many; $i++)
{
    if($abc['string_lookup'] == 'something_else')
    {
        $counter2++;
    }

}

echo "SECOND: ", (microtime(true) - $start), "\n";
too much php
Thanks! I'll lay off the coffee :)
ae
A: 

You might want to adjust the bool comparision a bit.

Doing a general if($var) is not a bool comparision (compared to the "string comparision").

Try the test again with if($abc['boolean_lookup'] == TRUE) or if($abc['boolean_lookup'] === TRUE) (2 vs. 3 equals signs).

I made a test including the bool comparision, and the three-equals signs comparisions aswell. And additionally a loop to do it 3 times, as the results may vary on a number of external factors.

Since the total time of script excution is fairly long this way I've lowereed the $how_many = 5000000; to $how_many = 3000000;

Here is the final script:

<?php
function DoTest(){

    $how_many = 3000000;
    $counter1 = 0;
    $counter2 = 0;
    $counter3 = 0;
    $counter4 = 0;
    $counter5 = 0;
    $counter6 = 0;

    $abc = array('boolean_lookup'=>TRUE, 'string_lookup'=>'something_else');

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['boolean_lookup']){
            $counter1++;
        }

    }
    echo "GENERAL-IF ON A BOOL: ", (microtime(true) - $start)*10, "<br />\n";

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['string_lookup']){
            $counter2++;
        }

    }
    echo "GENERAL-IF ON A STRING: ", (microtime(true) - $start)*10, "<br />\n";

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['boolean_lookup'] == TRUE){
            $counter3++;
        }

    }
    echo "TWO-EQUALL-IF ON A BOOL : ", (microtime(true) - $start)*10, "<br />\n";

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['string_lookup'] == 'something_else'){
            $counter4++;
        }

    }
    echo "TWO-EQUALL-IF ON A STRING : ", (microtime(true) - $start)*10, "<br />\n";

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['boolean_lookup'] === TRUE){
            $counter5++;
        }

    }
    echo "THREE-EQUALL-IF ON A BOOL : ", (microtime(true) - $start)*10, "<br />\n";

    $start = microtime(true);
    for($i = 0; $i < $how_many; $i++){
        if($abc['string_lookup'] === 'something_else'){
            $counter6++;
        }

    }
    echo "THREE-EQUALL-IF ON A STRING : ", (microtime(true) - $start)*10, "<br />\n";

}

$number_of_tests = 3;
for($i = 0; $i < $number_of_tests; $i++){
    echo "<br />\n<br />\n== Test #".($i+1)."<br />\n";
    DoTest();
}
?>

And the results:

== Test #1
GENERAL-IF ON A BOOL: 7.61245965958
GENERAL-IF ON A STRING: 7.49043941498
TWO-EQUALL-IF ON A BOOL : 8.92991065979
TWO-EQUALL-IF ON A STRING : 10.3996396065
THREE-EQUALL-IF ON A BOOL : 8.02039146423
THREE-EQUALL-IF ON A STRING : 9.25590991974


== Test #2
GENERAL-IF ON A BOOL: 7.74684906006
GENERAL-IF ON A STRING: 7.58201122284
TWO-EQUALL-IF ON A BOOL : 8.90240907669
TWO-EQUALL-IF ON A STRING : 10.2967596054
THREE-EQUALL-IF ON A BOOL : 8.08442115784
THREE-EQUALL-IF ON A STRING : 9.2577290535


== Test #3
GENERAL-IF ON A BOOL: 7.63362884521
GENERAL-IF ON A STRING: 7.5103187561
TWO-EQUALL-IF ON A BOOL : 8.92127037048
TWO-EQUALL-IF ON A STRING : 10.4210495949
THREE-EQUALL-IF ON A BOOL : 8.02319049835
THREE-EQUALL-IF ON A STRING : 9.25379991531

So, my conclusion is that when doing a comparision (with equals sign) the bool is the winner, no doubt.

However, when doing a simple plain general if()-statement the string returns earlier then the bool.

Some other day I might check out if there is a difference in returning true or false (ie. does it take longer to detect the opposite ?)

Greetings, Krinkle