Re: Improved zend_string API
| From: | Levi Morrison | Date: | Tue, 30 Jun 2015 14:34:30 +0000 |
| Subject: | Re: Improved zend_string API | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-86973@lists.php.net to get a copy of this message | ||
On Tue, Jun 30, 2015 at 8:15 AM, Bob Weinand <bobwei9@hotmail.com> wrote:
>> Am 30.06.2015 um 12:53 schrieb François Laupretre <francois@php.net>:
>>
>>> De : Bob Weinand [mailto:bobwei9@hotmail.com]
>>>
>>> Precisely. Instead of tight coupling to the structure, we now couple to the
>>> macro… and it's not like the macro will be left untouched once we change the
>>> underlying structure.
>>
>> There are different levels of encapsulation : 1st level can be seen as the C structure, 2nd
>> level is the macro (allows to change the structure organization), 3rd level provides separate
>> read-only getters and write-only setters. If you look at
>> https://github.com/php/php-src/pull/1381, you will see the API I
>> want to integrate (not sure there is enough time before 7.0 freeze). It doesn't use macros any
>> more but active methods/functions. There, ZSTR_LEN() is a pure getter, which cannot be used as
>> lvalue. ZSTR_SET_LEN() is the corresponding write-only setter. I don't say that such API is
>> supposed to resist any implementation change but it should already allow a lot. When we achieve this
>> encapsulation level on arrays/HashTables, we'll be much more comfortable with future potential
>> changes.
>>
>> I understand your pov. If any future change in the underlying implementation requires
>> changing the API, this API is much less valuable. You think that zend_string internal implementation
>> will never evolve without requiring API changes. I don't think the same, I make no assumption
>> on other's creativity, I just know that, if the need for a better isolation arises someday, it
>> will be too late. So, I prefer to have it from the beginning. In zend_string, the need comes more
>> from the countless number of locations accessing the API than from the implementation complexity. Of
>> course, when we have both, like on arrays, isolation is still more important.
>>
>> Once again, zend_string is just an example. Zval needs some work too but is somewhat easier
>> as an extensive API already exists and most people use it, it just needs to be made
>> 'stricter'. Making the zval API stricter (with separate getters/setters) will allow for a
>> lot of debugging/monitoring instrumentation to be added to the API. Some of them are also
>> interesting for zend_strings. Just imagine simple checks in debug mode ensuring the string length
>> remains in allocated bounds. If you set the length using a '->len' assignment or a
>> macro, it cannot be trapped and checked. It is really the simplest example of what encapsulation
>> makes possible. When we work on zend_string/smart_str integration, code can also be inserted to
>> measure the efficiency of various over-allocation policies. With you '->len', what will
>> you do ? "grep '--' '->len'
find . -type
>> f" and rewrite thousands of occurrences ?
>
> I see where you're heading to. But I still hold my position that you're overvaluing
> abstraction in that particular case. Like… it would be ideal to automatically reset the hash value
> on each change. Do we want that? No. It'd do millions of useless hash-resetting operations.
> So… what we end up? Having to manually control hash values. We always need to fallback to
> low-level control, even though we have an API. That's not good.
> It'd be nice to abstract it away, but that's at a cost we aren't willing to pay.
> You only can have a certain level of abstraction without paying the price.
>
> I think, zend_string * may evolve without structure changes. But in case we change the
> structures, something will have changed so drastically that the higher level APIs need change too.
> I doubt that it will allow a lot.
>
> Let's take your example with "stricter" API. What can you now debug/monitor?
> Like how a value changes? That you easily can right now with every smart C debugger… setting a
> watchpoint.
> Also, smart string is an own API, with dedicated functions. We can very well test that at that
> level. No need to leak that over onto zend_string *. Smart string is a high-level API on top of
> zend_string *, _using_ the primitive zend_string API.
>
> Oh, a check if it's in allocated bounds? Only issue is that we actually don't store
> the boundaries (also no reason to) … anyway, I can guarantee that the prefect abstraction will be
> leaky, or include a ton of functions operating on them. That's not the way to go.
> Example… reallocing a string without setting a length (to extend but not knowing the exact
> final length yet) … not possible, currently. I'm sure, if you search for cases where the
> abstraction is leaky, you'll find enough.
> Do NOT introduce leaky abstractions where it's not hiding complexity.
>
>>> Like … PHP 7 changed the semantics of Z_TYPE() macro… you can no longer
>>> assign directly to it. We anyway have to change our code.
>>> It's rare that such underlying changes don't leak through the API.
>>
>> No, we need to change our code because the zval API's encapsulation level was not high
>> enough. It type setters and getters had been already separate in PHP 5, switching to PHP 7
>> wouldn't have required changing our code. That's why defining access macros is not enough.
>> We need stricter 'methods', designed as services.
>
> Okay. Other example. Refcounts. The macro itself still works… just that it'll badly fail
> when you try to refcount a primitive type now. The changes leak on all levels … Oh sure. You could
> have added a branch for each refcount checking the type… Just that will cost precious
> instructions.
>
> Or IS_REFERENCE handling. A new type. Needs to be handled at all levels and beyond.
> Or having now Z_STR() … sure, Z_STRVAL(), Z_STRLEN() still work, but became inefficient to
> use.
>
> I could continue that list...
>
> Merci,
> Bob
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
Just to time in with my $0.02: I feel that using macros as an
abstraction in this case is bad practice. I believe that in *most*
cases macros as an abstraction is a bad practice. Furthermore, there
isn't any reason that zend_string_* functions cannot act as an
abstraction layer since zend_string's are passed by pointer.