From: php at richardneill dot org Operating system: PHP version: 5.4.13 Package: Performance problem Bug Type: Bug Bug description:optimisation for "for ($i=0; $i<count($array);$i++)" when $array is global
Description: ------------ If an array is counted inside a for-loop, this is normally slightly inefficient. $n = count ($array); //[1] optimised and a bit faster. for ($i=0; $i< $n;$i++){ //do stuff } for ($i=0; $i<count($array);$i++){ //[2] perfectly respectable speed. //do stuff //very nearly as fast as [1]. } BUT, if our for-loop is inside a function AND our $array is a global variable, then method [2] becomes really really slow (though method [1] remains unaffected). Below, the problematic function is add_slow(); the script does the same thing 4 ways to demonstrate that 3 of them work well and one works slowly. Test script: --------------- #!/usr/bin/php -ddisplay_errors=E_ALL <? echo "This demonstrates the problem with counting global arrays inside loops inside functions.\n"; $NUMBER = 10000; //adjust for your computer. for ($i = 0; $i< $NUMBER; $i++){ $data[$i] = "$i"; } function add_slow(){ //This is the problematic function. $data is global, and the count() is inside the for(). global $data; //It is REALLY slow: 4000 times slower than the others! $sum=0; for ($i = 0; $i < count($data); $i++){ $sum += $data[$i]; } echo "Total (slow) is $sum.\n"; } function add_fast(){ //This one is fine. The count() is optimised by taking it out of the for(). global $data; //... but we're still using a global array, so that's not the problem. $sum=0; $n = count($data); for ($i = 0; $i < $n; $i++){ $sum += $data[$i]; } echo "Total (fast) is $sum.\n"; } function add_local(){ //This one is also fine. The count() is NOT optimised, but it still runs almost as quickly. global $NUMBER; for ($i = 0; $i< $NUMBER; $i++){ $data[$i] = "$i"; } $sum=0; for ($i = 0; $i < count($data); $i++){ $sum += $data[$i]; } echo "Total (local) is $sum.\n"; } echo "Calling add_slow()...\n"; $t1 = microtime(true); add_slow(); $t2 = microtime(true); $time = round($t2 - $t1, 3); echo "Finished in $time seconds.\n\n"; echo "Calling add_fast()...\n"; $t1 = microtime(true); add_fast(); $t2 = microtime(true); $time = round($t2 - $t1, 3); echo "Finished in $time seconds.\n\n"; echo "Calling add_local()...\n"; $t1 = microtime(true); add_local(); $t2 = microtime(true); $time = round($t2 - $t1, 3); echo "Finished in $time seconds.\n\n"; echo "Not using a function...\n"; $t1 = microtime(true); $sum=0; for ($i = 0; $i < count($data); $i++){ //This one is in the main() scope, it's also fast. $sum += $data[$i]; } echo "Total (main loop) is $sum.\n"; $t2 = microtime(true); $time = round($t2 - $t1, 3); echo "Finished in $time seconds.\n\n"; ?> Expected result: ---------------- All 4 ways of summing this array should run in similar amounts of time (a few milliseconds). But actually add_slow() is 3900 times slower. Actual result: -------------- This demonstrates the problem with counting global arrays inside loops inside functions. Calling add_slow()... Total (slow) is 49995000. Finished in 7.86 seconds. Calling add_fast()... Total (fast) is 49995000. Finished in 0.002 seconds. Calling add_local()... Total (local) is 49995000. Finished in 0.006 seconds. Not using a function... Total (main loop) is 49995000. Finished in 0.002 seconds. -- Edit bug report at https://bugs.php.net/bug.php?id=64518&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=64518&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=64518&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=64518&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=64518&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=64518&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=64518&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=64518&r=needscript Try newer version: https://bugs.php.net/fix.php?id=64518&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=64518&r=support Expected behavior: https://bugs.php.net/fix.php?id=64518&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=64518&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=64518&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=64518&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=64518&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=64518&r=dst IIS Stability: https://bugs.php.net/fix.php?id=64518&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=64518&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=64518&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=64518&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=64518&r=mysqlcfg