Re: concatenating with "." or ","

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2008-08-27 at 12:27 +0200, Bernhard Kohl wrote:
> tedd wrote:
> > There are significant orders of magnitude difference between your results
> > and mine.
> > For example, it didn't make any difference if you used a comma or
> > concatenation, but in my system concatenation was 15 times faster than using
> > a comma. Interesting, I would have guessed it would have been the other way
> > around.
> 
> I refined the test, so that it is more random and therefore maybe more accurate.

What does random have to do with the echo, concatenaton, interpolation,
or heredoc functionality? I would presume these to be mutually
exclusive. As such your test adds noise to the problem and is more than
likely less accurate.

> ------------------------------------------------------------------------------
> For all those who want to try it out, here is the code:
> ------------------------------------------------------------------------------
> 
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
> <html xmlns="http://www.w3.org/1999/xhtml";>
> <head>
> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
> <title>Test for Tedd</title>
> </head>
> <body style="font-size: small;">
> <h1>Test Results</h1>
> <?php
> global $iterations, $results, $test_string;
> $iterations = 2048;
> $iterations2 = 128; // iterations for 2nd test
> $results1 = array(
>   "comma" => array("total_time" => 0, "count" => 0),
>   "concat" => array("total_time" => 0, "count" => 0),
>   "interpol" => array("total_time" => 0, "count" => 0),
>   "heredoc" => array("total_time" => 0, "count" => 0)
> 
> );

An array? You do realize that arrays are stored as some kind of tree
with O( lg n ) lookup? This means that it WILL take longer to access
some of those entries than it does for others. They can't all be sitting
at the root node of the tree. These tests shoul dhave been run
individually.

> $results2 = $results1;
> $test_array = array();
> $test_string = md5(time()); // a 32 character string
> $eval_strings = create_eval_strings();
> for ($i = 0; $i < $iterations; ++$i) $test_array[] =
> str_shuffle($test_string); // random strings

Aggain I'd like to point out that randomizing the string more than
likely does nothing for the benchmark.

> for ($i = 0; $i < $iterations; ++$i) test_method(rand(0,3));

A function call... to a less than simplistic function (yes simple
logically, complex when benchmarks should normally be run on the
simplest representation of the problem).

> function test_method($method) {
>   $start_time = $end_time = 0;
>   $test_array =& $GLOBALS['test_array'];
>   $test_string =& $GLOBALS['test_string'];
>   $eval_strings =& $GLOBALS['eval_strings'];
>   for ($i = 0; $i < 10; ++$i) {
>     $j = rand(0, $GLOBALS['iterations']);
>     $test_array[$j] = str_shuffle($test_array[$j]); // change some arr
> vals to outsmart any php speedup/cache
>   }
>   $arr2 = array(); // array for 2nd test
>   for ($i = 0; $i < $GLOBALS['iterations2']; ++$i) $arr2[] =
> $test_array[rand(0, $GLOBALS['iterations'])];
>   # 1st test will output # of iterations random strings
>   # 2nd test will output a sequence of #iterations2 random strings
>   switch ($method) {
>     case 0: // comma
>       # -----> TEST 1 <-----
>       ob_start();
>       $start_time = microtime(true);
>       foreach ($test_array as $array_value) {
> 	     echo $test_string, $array_value;
>       }
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results1"]["comma"]["total_time"] += abs($end_time -
> $start_time)*1000/$GLOBALS["iterations"];
>       ++$GLOBALS["results1"]["comma"]["count"];
>       # -----> TEST 2 <-----
>       ob_start();
>       $start_time = microtime(true);
>       eval($eval_strings['comma']);
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results2"]["comma"]["total_time"] += abs($end_time -
> $start_time)*1000;
>       ++$GLOBALS["results2"]["comma"]["count"];
>       break 1;

Do you mind if I scream here... output buffering, eval, internal
microtime function to measure the efficiency of multiple different
approaches? These are all going to add to the noise. You should use the
system's time command to determine actual time spent on the process.


>     case 1: // concatenation
>       # -----> TEST 1 <-----
>       ob_start();
>       $start_time = microtime(true);
>       foreach ($test_array as $array_value) {
> 	     echo $test_string.$array_value;
>       }
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results1"]["concat"]["total_time"] += abs($end_time -
> $start_time)*1000/$GLOBALS["iterations"];
>       ++$GLOBALS["results1"]["concat"]["count"];
>       # -----> TEST 2 <-----
>       ob_start();
>       $start_time = microtime(true);
>       eval($eval_strings['concat']);
>       $end_time = microtime(true);
>       ob_end_clean();
>       echo $eval_string."\n";
>       $GLOBALS["results2"]["concat"]["total_time"] += abs($end_time -
> $start_time)*1000;
>       ++$GLOBALS["results2"]["concat"]["count"];
>       break 1;
>     case 2: // interpolation
>       # -----> TEST 1 <-----
>       ob_start();
>       $start_time = microtime(true);
>       foreach ($test_array as $array_value) {
> 	     echo "{$test_string}{$array_value}";
>       }
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results1"]["interpol"]["total_time"] += abs($end_time
> - $start_time)*1000/$GLOBALS["iterations"];
>       ++$GLOBALS["results1"]["interpol"]["count"];
>       # -----> TEST 2 <-----
>       ob_start();
>       $start_time = microtime(true);
>       eval($eval_strings['interpol']);
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results2"]["interpol"]["total_time"] += abs($end_time
> - $start_time)*1000;
>       ++$GLOBALS["results2"]["interpol"]["count"];
>       break 1;
>     case 3: // heredoc
>       # -----> TEST 1 <-----
>       ob_start();
>       $start_time = microtime(true);
>       foreach ($test_array as $array_value) {
> 	     echo <<<TEST
> $test_string$array_value;
> TEST;
>       }
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results1"]["heredoc"]["total_time"] += abs($end_time -
> $start_time)*1000/$GLOBALS["iterations"];
>       ++$GLOBALS["results1"]["heredoc"]["count"];
>       # -----> TEST 2 <-----
>       ob_start();
>       $start_time = microtime(true);
>       eval($eval_strings['heredoc']);
>       $end_time = microtime(true);
>       ob_end_clean();
>       $GLOBALS["results2"]["heredoc"]["total_time"] += abs($end_time -
> $start_time)*1000;
>       ++$GLOBALS["results2"]["heredoc"]["count"];
>       break 1;
>   }
> }
> function create_eval_strings() { // returns the eval strings for the 4 methods
>   $strings = array();
>   $eval_string = 'echo'; // comma
>   for ($i = 0; $i < $GLOBALS['iterations2']; ++$i) $eval_string .= '
> $arr['.$i.'],';
>   $eval_string{strlen($eval_string) - 1} = ';';
>   $strings['comma'] = $eval_string;
>   $eval_string = str_replace(', ', '.', $eval_string); // concatenation
>   $strings['concat'] = $eval_string;
>   $eval_string = 'echo "'; //interpolation
>   for ($i = 0; $i < $GLOBALS['iterations2']; ++$i) $eval_string .=
> '{$arr['.$i.']}';
>   $eval_string .= '";';
>   $strings['interpol'] = $eval_string;
>   $eval_string = "echo <<<TEST\n"; // heredoc
>   for ($i = 0; $i < $GLOBALS['iterations2']; ++$i) $eval_string .=
> '$arr['.$i.']';
>   $eval_string .= "\nTEST;";
>   $strings['heredoc'] = $eval_string;
>   return $strings;
> }
> function get_result(&$result) {
>   $buffer = "";
>   foreach ($result as $key => $value) {
>     $avg_time = $value['total_time']/$value['count'];
>     $buffer .= "
>       <h3>{$key} Method</h3>
>       <p><strong>Number of Echoes:</strong> {$value['count']}</p>
>       <p><strong>Total time:</strong> {$value['total_time']} milliseconds</p>
>       <p><strong>Average time:</strong> {$avg_time} milliseconds</p>
>     ";
>   }
>   return $buffer;
> }
> $result1 = get_result($results1);
> $result2 = get_result($results2);
> echo <<<RESULTS
> 
> <h2>Results for $iterations cycles of echoing a 32-character string
> with a random 32-character string $iterations times:</h2>
> $result1
> <h2>Results for echoing $iterations2 random 32-character string
> $iterations times:</h2>
> $result2
> RESULTS;
> ?>
> </body>
> </html>

I don't mean to beat down on you, but this is not a good benchmark. I
will follow this post with a proper benchmark.

Cheers,
Rob.
-- 
http://www.interjinn.com
Application and Templating Framework for PHP


-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux