From: thuejk at gmail dot com Operating system: Linux PHP version: 5.2.1 PHP Bug Type: Performance problem Bug description: Poor perfomance of ".="
Description: ------------ In some cases, the ".=" operator can have poor performance. I have a production PHP program which a problem which I think is caused by this. Originally a task took 700 seconds to run. Some debug output found that a simple ".=" on a very long string took far too long. Tweaking the memory allocator to round up allocations to the nearest power of 2 decreased the run time to 60 seconds. My tweak was to insert uint pow_2 = 4; while (pow_2 < size) { pow_2 *= 2; } size = pow_2; into the top of _zend_mm_alloc_int() and _zend_mm_realloc_int() (I think) ".=" uses the Zend/zend_operators.c:concat_function() function. This function will reallocate the string with the minimum length needed for each concatenation. My tweaked memory allocator will allocate extra space in advance, which means realloc() returns immediately, which seems to make the difference. I have attached some code which reproduces the performance problem. I am actually not sure exactly what happens. The part for creating MM holes is taken from http://bugs.php.net/bug.php?id=40261 , so this may be the same bug, but I am not sure. Run time of attached test case with and without my tweak: [EMAIL PROTECTED] ~> time /usr/local/php-5.2.1/bin/php evil.php /usr/local/php-5.2.1/bin/php evil.php 1,04s user 0,01s system 99% cpu 1,047 total [EMAIL PROTECTED] ~> time /usr/local/php-5.2.1_clean/bin/php evil.php /usr/local/php-5.2.1_clean/bin/php evil.php 12,30s user 0,02s system 99% cpu 12,323 total Reproduce code: --------------- <?php error_reporting(E_ALL|E_STRICT); $num_increments = 100; $num_repeats = 1000; $increment = 50; /* Create some more holes to give the memory allocator something to * work with. */ $num = 5000; $a = Array(); for ($i=0; $i<$num; $i++) { $a[$i] = Array(1); } for ($i=0; $i<$num; $i++) { $b[$i] = $a[$i][0]; } unset($a); for ($i=0;$i<$num_repeats;$i++) { $evil = ""; for ($j=0;$j<$num_increments;$j++) { $evil .= str_repeat("a", $increment); } unset($evil); } ?> -- Edit bug report at http://bugs.php.net/?id=40809&edit=1 -- Try a CVS snapshot (PHP 4.4): http://bugs.php.net/fix.php?id=40809&r=trysnapshot44 Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=40809&r=trysnapshot52 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=40809&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=40809&r=fixedcvs Fixed in release: http://bugs.php.net/fix.php?id=40809&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=40809&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=40809&r=needscript Try newer version: http://bugs.php.net/fix.php?id=40809&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=40809&r=support Expected behavior: http://bugs.php.net/fix.php?id=40809&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=40809&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=40809&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=40809&r=globals PHP 3 support discontinued: http://bugs.php.net/fix.php?id=40809&r=php3 Daylight Savings: http://bugs.php.net/fix.php?id=40809&r=dst IIS Stability: http://bugs.php.net/fix.php?id=40809&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=40809&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=40809&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=40809&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=40809&r=mysqlcfg