Re: How deep is copy on write?

From: Date: Wed, 19 Jan 2011 19:05:23 +0000
Subject: Re: How deep is copy on write?
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-51324@lists.php.net to get a copy of this message
So it sounds like the general answer is that if you pass a complex array to a function by value and mess with it, data is duplicated for every item you modify and its direct ancestors up to the root variable but not for the rest of the tree. For objects, because of their "pass by handle"-type behavior you are (usually) modifying the same data directly so there's no duplication. Does that sound correct? Related: What is the overhead of a ZVal? I'm assuming it's a fixed number of bytes. --Larry Garfield On 1/19/11 11:27 AM, Gustavo Lopes wrote:
On Wed, 19 Jan 2011 14:23:49 -0000, Martin Scotta <martinscotta@gmail.com> wrote:
What about objects?
With objects less copying occurs because the object value (zval) data is actually just a pointer and an id that for most purposes works as a pointer. However, it should be said that while a copy of an array forces more memory to be copied, the inner zvals are not actually copied. In this snippet: $a = array(1, 2, array(3)); $b = $a; function separate(&$dummy) { } separate($a); the copy that occurs when you force the separation of the zval that is shared by $a and $b ($b = $a doesn't copy the array in $a to $b, it merely copies the zval pointer of $a to $b and increments its reference count) is just a shallow copy of hash table and a increment of the first level zvals' refcounts. This means the zvals that have their pointers stored in the array $a's HashTable are not themselves copied. Interestingly (or should I say, unfortunately), this happens even if the inner zvals are references. See http://php.net/manual/en/language.references.whatdo.php the part on arrays.
class Foo { public $foo; } function test($o) { $o->foo->foo->foo = 2; } $bar = new Foo; $bar->foo = new Foo; $bar->foo->foo = new Foo; test( $bar );
This example shows no copying (in the sense of "new zval allocation on passing or assignment") at all.
--- Also... is it better to pass an object as a parameter rather than many values? function withValues($anInteger, $aBool, $aString) { var_dump($anInteger, $aBool, $aString); } function withObject(ParamOject $o) { var_dump( $o->theInteger(), $o->theBool(), $o->theString() ); }
It should be indifferent. In normal circumstances, there is no zval copying at all (only the pointers of arguments' symbols are copied). Only when you start throwing references into the mix will you start forcing copied.


« previous php.internals (#51324) next »