#50894 [NEW]: no-op cast triggers copy-on-write

From: Date: Mon, 01 Feb 2010 06:13:34 +0000
Subject: #50894 [NEW]: no-op cast triggers copy-on-write
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-147075@lists.php.net to get a copy of this message
From: lee at projectmastermind dot com Operating system: Linux, OSX PHP version: 6SVN-2010-02-01 (snap) PHP Bug Type: Performance problem Bug description: no-op cast triggers copy-on-write Description: ------------ given a value with a particular type, casting it to that same type should essentially be a no-op -- once it is determined that the operand already has the correct type, no further action needs to be taken. Ex: $a = array(); $b = (array)$a; In this example, $a is already an array, so this should be a simple assignment operation. $b should get a "lazy" copy of $a via PHP's copy-on-write policy. Instead, the cast operation seems to force an immediate (non-lazy) full copy. This creates a huge potential for hidden performance problems, as it causes code that *looks* like it would run in constant time [O(1)] to actually require linear time [O(n)] (where n represents the size of the data being copied). I have verified that this issue does exist for string types as well. I assume that it applies to all PHP types. Of course it becomes a significant performance issue primarily for types that can hold large amounts of data, where the data is duplicated whenever the zval is duplicated (AFAIK, this is only string and array). I have verified this on the following versions of php: 5.2.6 5.2.8 6.0.0-dev (php6.0-201001312130) Reproduce code: --------------- <?php for( $z=1; $z<5; ++$z ) { $a = array_fill(0, 100*$z, '0'); $t_start = microtime(true); for($i=0;$i<100000;++$i) { // O(n) [should be constant time, but isn't] // cast triggers non-lazy copy // $b = (array)$a; // O(1) [constant time, as expected] // (comment above, and uncomment here for comparison) // //$b = $a; } $t_elapsed = (microtime(true)*1000)-($t_start*1000); printf( "(%d elements * %d copies): %f ms\n\n", 100*$z, $i, $t_elapsed ); } Expected result: ---------------- (100 elements * 100000 loops): 11.264160 ms (200 elements * 100000 loops): 11.363037 ms (300 elements * 100000 loops): 11.208984 ms (400 elements * 100000 loops): 11.809082 ms NOTE: the time stays roughly constant as the number of elements increases -- the assignments are copy-on-write, so no significant performance hit is incurred. Actual result: -------------- (100 elements * 100000 copies): 736.453613 ms (200 elements * 100000 copies): 1448.991211 ms (300 elements * 100000 copies): 2130.541016 ms (400 elements * 100000 copies): 2823.362793 ms NOTE: the time increases as the size of the array increases. (This happens with large strings too). This is a good indicator that a copy is being made [non-lazily] when the cast is applied. -- Edit bug report at http://bugs.php.net/?id=50894&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=50894&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=50894&r=trysnapshot53 Try a snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=50894&r=trysnapshot60 Fixed in SVN: http://bugs.php.net/fix.php?id=50894&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=50894&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=50894&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=50894&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=50894&r=needscript Try newer version: http://bugs.php.net/fix.php?id=50894&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=50894&r=support Expected behavior: http://bugs.php.net/fix.php?id=50894&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=50894&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=50894&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=50894&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=50894&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=50894&r=dst IIS Stability: http://bugs.php.net/fix.php?id=50894&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=50894&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=50894&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=50894&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=50894&r=mysqlcfg

« previous php.bugs (#147075) next »