Re: Improved zend_string API

From: 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.

« previous php.internals (#86973) next »