Bug #64518 [Nab]: optimisation for "for ($i=0; $i<count($array);$i++)" when $array is global
| From: | sixd@php.net | Date: | Tue, 26 Mar 2013 21:04:03 +0000 |
| Subject: | Bug #64518 [Nab]: optimisation for "for ($i=0; $i<count($array);$i++)" when $array is global | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-178132@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=64518&edit=1
ID: 64518
Updated by: sixd@php.net
Reported by: php at richardneill dot org
Summary: optimisation for "for ($i=0; $i<count($array);$i++)"
when $array is global
Status: Not a bug
Type: Bug
Package: Performance problem
PHP Version: 5.4.13
Block user comment: N
Private report: N
New Comment:
You can contribute documentation updates at https://edit.php.net.
If you don't have an account, use "anonymous" in the "VCS login" field.
Previous Comments:
------------------------------------------------------------------------
[2013-03-26 16:55:28] php at richardneill dot org
I see your point about optimisations being too low-level, but some of these things are hugely
different in performance. Try running the following script:
http://www.richardneill.org/tmp/php-perf.txt
I notice 3 things.
1) Updating a variable in-place is 1000x slower than creating a new one.
Fast: $n = count($data);
Slow: $data = count($data);
2) Using $GLOBALS['var'] inside a function is very similar to using the same variable in
the main scope. Using "global $var" is always at least a bit slower.
3) Using global for just reading a variable is 100x slower than reading it from $GLOBALS inside a
function.
Fast: $n = count($GLOBALS['data'])
Slow: global $data; $n = count ($data)
I think that (3) might be a bug.
I also think that these differences are far from negligible, and so PHP's documentation
*should* mention them.
------------------------------------------------------------------------
[2013-03-26 15:57:08] nikic@php.net
It's not always faster. Which one is faster is not very predictable without good knowledge of
the engine. We don't address such low-level details in the manual.
------------------------------------------------------------------------
[2013-03-26 15:15:38] php at richardneill dot org
> The issue you are seeing is that
global $data is a by-reference
> fetch
> (unlike $data = $GLOBALS['data'], which is by-value).
> The by-ref pass
> prevents us from doing a copy-on-write optimization when passing the array to
> the by-value count() function, so the array has to be copied every single time.
Thanks for the explanation. That makes some sense as an explanation. However, it also implies that
use of "$GLOBALS['var']" is always faster, sometimes much faster, than
"global $var". If this is true, might I suggest that this is a documentation issue that
should be addressed?
------------------------------------------------------------------------
[2013-03-26 13:34:40] nikic@php.net
The issue you are seeing is that global $data is a by-reference fetch (unlike
$data = $GLOBALS['data'], which is by-value). The by-ref pass prevents us
from doing a copy-on-write optimization when passing the array to the by-value count() function, so
the array has to be copied every single time.
The specific count() case is something we could optimize by adding a read-only passing mode for
function arguments (that never separates zvals). As that is something that's also useful for a
few other things, it might well be worth doing.
------------------------------------------------------------------------
[2013-03-26 06:34:44] php at richardneill dot org
... and getting closer to the source of the problem...
function a(){ //about 1400 us
global $data;
$n = $data;
}
function b(){ //much much quicker: about 18us
$n = $GLOBALS['data'];
}
Something is definitely wrong here, that makes "global" so much slower than
$GLOBALS.
Also, this isn't a read-only optimisation which makes b() much quicker than a();
it still applies even when we want to copy back into the global scope.
Consider:
function x(){
$n = $GLOBALS['data'];
$GLOBALS['data'] = count($n);
}
and x() is always about as fast as b().
A secondary problem: if x() is rewritten as:
function y(){
$GLOBALS['data'] = count($GLOBALS['data']);
}
then it can be either fast or slow depending on whether other function calls
contain "global $data" or not.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=64518
--
Edit this bug report at https://bugs.php.net/bug.php?id=64518&edit=1