Bug #64518 [Nab]: optimisation for "for ($i=0; $i<count($array);$i++)" when $array is global

From: 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

« previous php.bugs (#178132) next »