Re: Analysis of property visibility, immutability, and cloning proposals
| From: | Olle Härstedt | Date: | Wed, 30 Dec 2020 20:16:58 +0000 |
| Subject: | Re: Analysis of property visibility, immutability, and cloning proposals | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-112683@lists.php.net to get a copy of this message | ||
2020-12-30 19:50 GMT, Olle Härstedt <olleharstedt@gmail.com>:
> On Wed, 30 Dec 2020, 20:27 Larry Garfield, <larry@garfieldtech.com> wrote:
>
>>
>> > > 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.
>>
>
> Ok. You have a benchmark for this? I can make one otherwise, for the query
> example.
>
> It worries me a little that immutablility is pushed into the ecosystem as a
> silver bullet. Main reason functional languages are using it is because
> ownership is a newer concept, so it hasn't been adapted as much.
Tiny benchmark here:
https://gist.github.com/olleharstedt/eaaf1dd40be541f84aa0f3954a0ea54a
Running this on my ARM machine with PHP 7.2 gives ~1.2s for the
immutable loop, ~0.35s for the mutable one, meaning immutability is
~3x as expensive performance wise. And this is for a SMALL object - I
suspect the performance hit will grow the bigger the class gets (more
properties to clone). Correct me if I'm wrong. :/
Olle