Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:51330 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 40153 invoked from network); 19 Jan 2011 22:45:20 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 19 Jan 2011 22:45:20 -0000 Authentication-Results: pb1.pair.com smtp.mail=mail_ben_schmidt@yahoo.com.au; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=mail_ben_schmidt@yahoo.com.au; sender-id=unknown; domainkeys=good Received-SPF: error (pb1.pair.com: domain yahoo.com.au from 209.191.107.127 cause and error) DomainKey-Status: good X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: mail_ben_schmidt@yahoo.com.au X-Host-Fingerprint: 209.191.107.127 smtp144.mail.mud.yahoo.com Received: from [209.191.107.127] ([209.191.107.127:32909] helo=smtp144.mail.mud.yahoo.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 0A/32-41614-F79673D4 for ; Wed, 19 Jan 2011 17:45:20 -0500 Received: (qmail 56008 invoked from network); 19 Jan 2011 22:45:17 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com.au; h=DKIM-Signature:Received:X-Yahoo-SMTP:X-YMail-OSG:X-Yahoo-Newman-Property:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding; b=qrcN/uO9vSSiOy3hME08d5NocECCb2ejTwMnpy6gU7xHED0Rj2Mq19iIDh7TzISmYs2q8iNrnGavvS6uj+qDCp7W6st4bA8Wux+GknNwzNP0in7dwX3/DmusSYUwVgCu6e9a7+fgB5JgYFY9GeCLeNTlj6GhL3xVgWDvwks86L8= ; DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com.au; s=s1024; t=1295477117; bh=RzEdLvCo6UtpwXIlAfGeARmGOPs2rkA3U8n1tvINn8I=; h=Received:X-Yahoo-SMTP:X-YMail-OSG:X-Yahoo-Newman-Property:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding; b=e1okV6MtfIjzxsSTMYk6h6SgwQlrXvrlAXoi7uZPSvdAKD4SeqJfboyLSUoQskwTDIsmY1k6ophn+AFXbzYhWIl+L1M8LDmOMP5YkPd53j+6GJAXGmag6HoL606xHbDpLl9b46mN1kVuRc0TO65A+q2GpiBBrVkj2aitZlkS+cM= Received: from thought.local (mail_ben_schmidt@124.148.147.119 with plain) by smtp144.mail.mud.yahoo.com with SMTP; 19 Jan 2011 14:45:16 -0800 PST X-Yahoo-SMTP: enFMnPSswBAexaHyzgobwuUTrYOhZdJ0KRA2SjA- X-YMail-OSG: 3knAvrUVM1myQ66pQskAZwZ0e5889G3fXHJN6dcQKvVFPKZ C6YZDYY..OdZFPQzYxMUZFwMSKyQawhcVykXA3_Np1JZMM7DS3vQuQLf5VAp rh5csOj6n4pszXlsa1gx2uc5Cgumvl2uFv2mLp7i2QShltifGk78GFsCuhsU 6m2jtPpKav40wyg18.VLBYNEMr81XFB5rZpX3DfcxODGdt_qoWJqLQoNMPk6 ddfa9S53qPCwd6_A68VfaUIVbnK6c9QbE0uyFZfLaDI0DhcWNsjJP0eCYqBi BMvg948yLjWjn0rAf X-Yahoo-Newman-Property: ymail-3 Message-ID: <4D37697A.3090900@yahoo.com.au> Date: Thu, 20 Jan 2011 09:45:14 +1100 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-GB; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7 ThunderBrowse/3.3.4 MIME-Version: 1.0 To: "larry@garfieldtech.com" CC: "internals@lists.php.net" References: <201101190045.31781.larry@garfieldtech.com> <4D368C58.2040903@yahoo.com.au> <201101190109.52250.larry@garfieldtech.com> <4D369473.4040608@yahoo.com.au> <4D3735F3.7020502@garfieldtech.com> In-Reply-To: <4D3735F3.7020502@garfieldtech.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] How deep is copy on write? From: mail_ben_schmidt@yahoo.com.au (Ben Schmidt) On 20/01/11 6:05 AM, larry@garfieldtech.com wrote: > 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? Yes. > Related: What is the overhead of a ZVal? I'm assuming it's a fixed > number of bytes. It seems not, though a zval has a fixed size. What that size is will depend on the compiler and architecture of the system being used, or at least on the ABI. From zend.h: typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; }; The zvalue_value union will probably be 8 or 12 bytes, depending on the architecture. The whole struct will then probably be between 14 and 24 bytes, depending on the architecture and structure alignment and so on. For my system: $ cd php-5.3.3 $ ./configure $ cd Zend $ gcc -I. -I../TSRM -x c - < #include "zend.h" > int main(void) { > printf("%lu\n",sizeof(zval)); > return 0; > } > END $ file ./a.out ./a.out: Mach-O 64-bit executable $ ./a.out 24 $ gcc -I. -I../TSRM -arch i386 -x c - < #include "zend.h" > int main(void) { > printf("%lu\n",sizeof(zval)); > return 0; > } > END $ file ./a.out ./a.out: Mach-O executable i386 $ ./a.out 16 You can figure out what you think the overhead is from that. For a string, arguably the whole structure is overhead, since the string is stored elsewhere via pointer. Likewise for objects. For a double, the payload is 8 bytes, and stored in the zval, so there's less overhead. An integer, with a payload of 4 bytes, is somewhere in between. Ben. > > --Larry Garfield > > On 1/19/11 11:27 AM, Gustavo Lopes wrote: >> On Wed, 19 Jan 2011 14:23:49 -0000, Martin Scotta >> 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. >> >> >