note 98248 deleted from language.references by danbrown
| From: | danbrown@php.net | Date: | Thu, 03 Jun 2010 23:08:51 +0000 |
| Subject: | note 98248 deleted from language.references by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-169874@lists.php.net to get a copy of this message | ||
Note Submitter: tomas at matfyz dot cz
----
Thanks midir and bytepirate for very valuable comments. After seeing the figures in the phparch
article mentioned everything is clear now - PHP's references are broken by design regarding
efficiency, kind of "copy on reference" :-) which results in useless data copying when you
use some value in both static and "referenced" variables. See the following example
<?php
$iterations = 6000;
$a = str_repeat("X", 6000);
$starttime = microtime(true);
for ($i = 0; $i <= $iterations; $i++) {
$ar[$i] = $a; // there is actually no copying here!
}
echo (microtime(true) - $starttime) . " seconds expired\n";
$starttime = microtime(true);
for ($i = 0; $i <= $iterations; $i++) {
$item = &$ar[$i];
// "copy on reference" - the copying is done here!
// remove the reference (assign it normally) and it will go fast!
// it gives the same result if you pass it to function by reference
}
echo (microtime(true) - $starttime) . " seconds expired\n";
?>
The first for loop runs fast but the second one takes much much more. The contrary to what
you'd expect! The first loop is optimized well by "copy on write" but the second one
is a "copy on reference" trap and I think should be fixed in PHP.
Bytepirate's example works even if we use the original variable instead of the new
"referenced", and if we call an empty function:
<?php
$strlen=60000;
$bstring=str_repeat("X",$strlen);
$astring=&$bstring; // remove this line and it will go fast!
$starttime=microtime(true);
for($i=0;$i<=$strlen;$i++){
f($bstring); // 1ST CHANGE - even if you use the original value, it is also "poissoned"!
// copying is done here, very slow
}
echo (microtime(true)-$starttime)." seconds expired\n";
function f($s) {} // make $s passed by reference and it will also go fast!
?>
(This example looks still little artificial, but you can instead of
"$astring=&$bstring" statement place the for loop into new "function
g(&$bstring)", which is very real example!)
This example shows that the "$astring=&$bstring" command is toxic also to the $bstring
variable - every normal use of it (assignment, passing by value to function) will result in copying.
But if you use it as a reference only then no copying will be done.
CONCLUSION:
1) NEVER use the references as an optimization! It will go slower!
2) use references only if you must
3) if you use them, remember that every normal use (normal assignment, passing by value) of both the
referenced and referencing variables will result in data copying! If you use them as references no
copying is done.