Edit report at https://bugs.php.net/bug.php?id=64518&edit=1

 ID:                 64518
 Updated by:         s...@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] ni...@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] ni...@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

Reply via email to