> > That's a good summary of why immutability and with-er methods (or some
> > equivalent) are more ergonomic.
> >
> > Another point to remember: Because of PHP's copy-on-write behavior, full on
> > immutability doesn't actually waste that much memory.  It does use up some,
> > but far less than you think.  (Again, based on the tests MWOP ran for PSR-7
> > a ways back.)
> 
> I thought copy-on-write was only for arrays, not objects?
> 
> Olle

Copy on write applies to all values; the caveat is that with objects, the value 
being copied is the handle that points to an object in memory, rather than the 
object itself.  That means passing an object by reference can do some seriously 
unexpected things, which is why you basically never do so.

The point here is that if you have an object with 15 internal properties, it's 
memory usage is 15 zvals plus one zval for the object, plus one zval for the 
variable that points to it.  (I'm over-simplifying here.  A lot.)  If you pass 
it to a function, only the one zval for the handle is duplicated, which is the 
same as for an integer.

If you clone the object, you don't duplicate 15+1 zvals.  You duplicate just 
the one zval for the object itself, which reuses the existing 15 internal 
property entries.  If in the new object you then update just the third one, PHP 
then duplicates just that one internal zval and modifies the new one.  So you 
still are using only 18 zvals, not 36 zvals.  (Engine people: Yes, I am *very* 
over-simplifying.  I know.)

Basically, what in most languages would require manually implementing 
"immutable data structures" we get for free in PHP, which is seriously sweet.

The net result is that a with-er chain like this:

$foo2 = $foo->withBar('x')->withBaz('y')->withBeep('z');

is way, way less expensive than it looks, both on memory and CPU.  It is more 
expensive than setters, but not by much.

That's why I don't think the distinction between unique and immutable mentioned 
up-thread is that big of a deal in PHP, specifically.  Yes, they're different 
things, but the cost of them is not all that different because of CoW, so 
considering them separately is not as important as it would be in a language 
that doesn't automatically do CoW in the background for us.

(Whoever in the 90s decided to bake CoW into the engine, thank you.  It's an 
incredibly nice foundational feature.)

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to