<?php header('Content-Type: text/html; charset=utf-8');


    
# @param: time    execute the microtime test.
    # @param: for     execute the for loop test.
    # @param: foreach execute the foreach loop test.

    # Horizontal divider.
    
for ($i 0$i 80$i++) $div .= '#'$div .= "\n";

    function 
mtime($s) {
        
# Compute the difference of stop/start timestamp
        # and return a µs format.
        
return (microtime(true) - $s) * 1000000;
    }

    echo <<<EOS
<pre>$div# \$Id: bench.php,v 1.0 2009-04-24 09:30:31 +0200 uwalter Exp $
$div

EOS;

    
# Where are we actually?
    
$host $_SERVER['HTTP_HOST'];
    
$path str_replace($_SERVER['DOCUMENT_ROOT'], ''dirname(__FILE__));
    
$http preg_replace('#^(Apache/(\d+\.?)+).*$#''$1'$_SERVER['SERVER_SOFTWARE']);
    
$php  preg_replace('#^((\d+\.?)+).*$#''$1'phpversion());
    
# Note that with other HTTP server softwares such as httpdlight or IIS,
    # you need to modify the regular expression!

    # Create hyper links.
    
$bench '<a href="http://phpbench.com" target="_blank">http://phpbench.com</a>';
    
$link  '<a href="http://'.$host.$path.'/hbench.php" target="_blank">http://'.$host.$path.'/hbench.php</a>';
    
$xmpl  '<a href="http://'.$host.$path.'/bench.php?time&for">http://'.$host.$path.'/bench.php?time&for</a>';
    
$ncsa  '<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" target="_blank">creativecommons.org</a>';

    echo <<<EOS
Title:     PHP performance case study
Copyright: Uwe Walter, Ninja Media Group. All rights reserved.
License:   CC by NC-SA, $ncsa
Inspired:  This script was inspired by $bench and a few cooled
           bottles of Altenmünster Maibock. But since I'm a Shell and Perl
           programmer too, and I really love it, this one here is a little more
           archaic. No fancy formatting but simple text output. I just want to
           give you the needed information.

           In some cases you will wonder about the results, especially regarding
           the comparison of print() and echo(). There ARE cases, where a print
           is MUCH faster than an echo(). So you cannot simply say echo() IS
           faster than print(). ;-)

Note:      This script, in its actual version, is just the beginning!
           I will continue development as I'll find the time to.
 
Environment:

    httpd: $http
    PHP:   $php

Description:

    Used for time measurement is the PHP function microtime().

    microtime() returns a string containing a whitespace separated list of two
    elements, where the first is the fractional place and the last are seconds
    as a cut integer. The added string is the unix timestamp with microsends.

Usage:

    Every performance test has to be explicitely activated over passed GET
    parameters. For example if you want to see the microtime test, pass 'time'
    to bench, and so on.

    Example:

        $xmpl

    To see the complete bench script respectively the available parameters,
    please call:

        $link


EOS;

    
############################################################################
    # How goes the time?
    ############################################################################

    
if (isset($_GET['time'])) {

        echo 
$div'# How the time goes'"\n"$div"\n";

        function 
getMS($mask=0x0000) {

            
# Get UNIX timestamp with microseconds (PHP4 style).

            
list($msec$sec) = explode(' 'microtime());

            
# We use a bit mask here. The fastest comparison available!
            
if     ($mask 0x0001) return $msec $sec;
            elseif (
$mask 0x0002) return $msec;
            elseif (
$mask 0x0004) return $sec;
            else                    return 
0;
        }

        echo 
'MICROTIME RETURN VALUE:'"\n\n\t"microtime(), "\n\n";

        
printf("PHP4-MSEC: %17.6f sec\n",   getMS(0x0002));
        
printf("PHP4-SEC:  %17.6f sec\n\n"getMS(0x0004));

        
printf("PHP4-ALL:  %17.6f sec\n",   getMS(0x0001));
        
printf("PHP5-ALL:  %17.6f sec\n\n"microtime(true));

        
$a microtime(true); # <= PHP5 style
        
usleep(1000000);      # Wait one second
        
$b microtime(true);
        
$c $b $a;

        
printf("START:     %17.6f sec\n",   $a);
        
printf("STOP :     %17.6f sec\n\n"$b);

        
printf("DIFF :     %17.6f s\n",    $c);
        
printf("DIFF :     %17.6f ms\n",   $c 1000);
        
printf("DIFF :     %17.6f µs\n\n"$c 1000000);
    }

    
############################################################################
    # for loops on a sequential array
    ############################################################################

    
if (isset($_GET['for'])) {

        
# Prepare the sequential array to loop through.
        
for ($i 0$i 1000$i++) $array[] = $i;

        echo 
$div,
            
'# for loops with print() on a sequetial array.'"\n",
        
$div"\n";

        
# Begin 'for' tests.
        
$start microtime(true);
        for (
$i 0$i count($array); $i++) print $array[$i];
        
$stop1 mtime($start);

        
$start microtime(true);
        for (
$i 0$k count($array); $i $k$i++) print $array[$i];
        
$stop2 mtime($start);

        
$start microtime(true);
        
$z count($array);
        for (
$i 0$i $z$i++) print $array[$i];
        
$stop3 mtime($start);

        
$start microtime(true);
        while (
$out array_shift($array)) print $out;
        
$stop4 mtime($start);
    
        echo 
'

Legend:
i < c == for ($i = 0; $i < count($array); $i++) print $array[$i]
i < k == for ($i = 0, $k = count($array); $i < $k; $i++) print $array[$i]
i < z == $z = count($array); for ($i = 0; $i > $z; $i++) print $array[$i]
shift == while ($out = array_shift($array)) print $out

'
;
        
# Print 'for' tests.
        
printf("i < c: %16.6f µs\n",   $stop1);
        
printf("i < k: %16.6f µs\n",   $stop2);
        
printf("i < z: %16.6f µs\n",   $stop3);
        
printf("shift: %16.6f µs\n\n"$stop4);

        
########################################################################

        # Prepare array to loop through again.
        
for ($i 0$i 1000$i++) $array[] = $i;

        echo 
$div,
            
'# for loops with echo() on a sequetial array.'"\n",
        
$div"\n";

        
# Begin 'for' tests.
        
$start microtime(true);
        for (
$i 0$i count($array); $i++) echo $array[$i];
        
$stop1 mtime($start);

        
$start microtime(true);
        for (
$i 0$k count($array); $i $k$i++) echo $array[$i];
        
$stop2 mtime($start);

        
$start microtime(true);
        
$z count($array);
        for (
$i 0$i $z$i++) echo $array[$i];
        
$stop3 mtime($start);

        
$start microtime(true);
        while (
$out array_shift($array)) echo $out;
        
$stop4 mtime($start);

        echo 
'

Legend:
i < c == for ($i = 0; $i < count($array); $i++) echo $array[$i]
i < k == for ($i = 0, $k = count($array); $i < $k; $i++) echo $array[$i]
i < z == $z = count($array); for ($i = 0; $i > $z; $i++) echo $array[$i]
shift == while ($out = array_shift($array)) echo $out

'
;

        
# Print 'for' tests.
        
printf("i < c: %16.6f µs\n",   $stop1);
        
printf("i < k: %16.6f µs\n",   $stop2);
        
printf("i < z: %16.6f µs\n",   $stop3);
        
printf("shift: %16.6f µs\n\n"$stop4);
    }

    
############################################################################
    # foreach loops on an associative array
    ############################################################################

    
if (isset($_GET['foreach'])) {

        for (
$i 0$i 1000$i++) $array["$i"] = $i;
        echo 
$div,
            
'# for/foreach loops with print() on an associative array.'"\n",
        
$div"\n";

        
# foreach loops
        
$start microtime(true);
        foreach (
$array as $a) print $a;
        
$stop1 mtime($start);

        
$start microtime(true);
        foreach (
$array as $a => $b) print $a[$b];
        
$stop2 mtime($start);

        
$start microtime(true);
        foreach (
array_keys($array) as $a) print $array[$a];
        
$stop3 mtime($start);

        
$start microtime(true);
        foreach (
array_values($array) as $a) print $a;
        
$stop4 mtime($start);

        echo 
'

Legend:
as a      == foreach ($array as $a) print $a;
a as b    == foreach ($array as $a => $b) print $array[$a];
keys as a == foreach (array_keys($array) as $a) print $array[$a];
vals as a == foreach (array_values($array) as $a) print $a;

'
;
        
printf("as a:      %16.6f µs\n",   $stop1);
        
printf("a as b:    %16.6f µs\n",   $stop2);
        
printf("keys as a: %16.6f µs\n",   $stop3);
        
printf("vals as a: %16.6f µs\n\n"$stop4);

        
########################################################################

        
echo $div,
            
'# for/foreach loops with echo() on an associative array.'"\n",
        
$div"\n";

        
# foreach loops
        
$start microtime(true);
        foreach (
$array as $a) echo $a;
        
$stop1 mtime($start);

        
$start microtime(true);
        foreach (
$array as $a => $b) echo $a[$b];
        
$stop2 mtime($start);

        
$start microtime(true);
        foreach (
array_keys($array) as $a) echo $array[$a];
        
$stop3 mtime($start);

        
$start microtime(true);
        foreach (
array_values($array) as $a) echo $a;
        
$stop4 mtime($start);

        echo 
'

Legend:
as a      == foreach ($array as $a) echo $a;
a as b    == foreach ($array as $a => $b) echo $array[$a];
keys as a == foreach (array_keys($array) as $a) echo $array[$a];
vals as a == foreach (array_values($array) as $a) echo $a;

'
;
        
printf("as a:      %16.6f µs\n",   $stop1);
        
printf("a as b:    %16.6f µs\n",   $stop2);
        
printf("keys as a: %16.6f µs\n",   $stop3);
        
printf("vals as a: %16.6f µs\n\n"$stop4);
    }

    
############################################################################
    # To be continued ....
    ############################################################################

    
echo $div'# EOF'"\n"$div"\n"'</pre>';
?>