# Fast zend_parse_parameters API

- Thread: https://externals.io/message/77053
- Original archive: https://news-web.php.net/php.internals/77053
- Started by Bob Weinand on 2014-09-04T12:23:02+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #77053 — Bob Weinand — 2014-09-04T12:23:02+00:00

URL: https://externals.io/message/77053#77053

After a long time… back to our fast_zpp RFC.

Initially Dmitry proposed to have two different APIs, one for the fast version, one for current version:
#if FAST_ZPP
    /* new API */
#else
    /* old style zend_parse_parameters API */
#endif

I don't really like the idea of having two different APIs, so I'd rather propose to use one same public API for both.
That API should, depending on some compile-time flag (per file or globally in zend_API.h), either convert to the usual variadic style function, or expand to the new fast variant of API parsing (with directly inlining parameter type specific functions).

What do you think about having one unified API for both, instead of the current (like it's in some places in master branch currently)?
(p.s.: The rewrite of the current API can be done safely via some PHP script I wrote)

Also, there is the question about how to structure the API; we (I and Dmitry) basically have now two different proposals:


ZEND_PARSE_PARAMETERS_START(3, 5)
    Z_PARAM_ZVAL(regex)
    Z_PARAM_ZVAL(replace)
    Z_PARAM_ZVAL(subject)
    Z_PARAM_OPTIONAL
    Z_PARAM_LONG(limit)
    Z_PARAM_ZVAL_EX(zcount, 0, 1)
ZEND_PARSE_PARAMETERS_END_EX(return);


OR


zend_parse_parameters(ZPP_ZVAL(regex) ZPP_ZVAL(replace) ZPP_ZVAL(subject) ZPP_OPTIONAL ZPP_LONG(limit) ZPP_ZVAL_EX(zcount, ZPP_BY_REF), {
    return;
})


We'd like to have some discussions about what API to use for the next years. If you have some better API, feel free to propose it.

Thanks,
Bob

---

## #77054 — Andrea Faulds — 2014-09-04T12:27:43+00:00

URL: https://externals.io/message/77053#77054 · In reply to: #77053

> After a long time… back to our fast_zpp RFC.
> 
> Initially Dmitry proposed to have two different APIs, one for the fast version, one for current version:
> #if FAST_ZPP
>    /* new API */
> #else
>    /* old style zend_parse_parameters API */
> #endif
> 
> I don't really like the idea of having two different APIs, so I'd rather propose to use one same public API for both.
> That API should, depending on some compile-time flag (per file or globally in zend_API.h), either convert to the usual variadic style function, or expand to the new fast variant of API parsing (with directly inlining parameter type specific functions).
> 
> What do you think about having one unified API for both, instead of the current (like it's in some places in master branch currently)?
> (p.s.: The rewrite of the current API can be done safely via some PHP script I wrote)

This is actually quite an interesting idea. If you think about it, there’s no reason the macros couldn’t expand to zend_parse_parameters.

> 
> Also, there is the question about how to structure the API; we (I and Dmitry) basically have now two different proposals:
> 
> 
> ZEND_PARSE_PARAMETERS_START(3, 5)
>    Z_PARAM_ZVAL(regex)
>    Z_PARAM_ZVAL(replace)
>    Z_PARAM_ZVAL(subject)
>    Z_PARAM_OPTIONAL
>    Z_PARAM_LONG(limit)
>    Z_PARAM_ZVAL_EX(zcount, 0, 1)
> ZEND_PARSE_PARAMETERS_END_EX(return);
> 
> 
> OR
> 
> 
> zend_parse_parameters(ZPP_ZVAL(regex) ZPP_ZVAL(replace) ZPP_ZVAL(subject) ZPP_OPTIONAL ZPP_LONG(limit) ZPP_ZVAL_EX(zcount, ZPP_BY_REF), {
>    return;
> })
> 
> 
> We'd like to have some discussions about what API to use for the next years. If you have some better API, feel free to propose it.

Neither is that good, though I might prefer the first one.

Perhaps we should move this out of functions altogether, and instead have parameter types be attributes of the function? I’m not sure if it’s possible, but it would be awesome if we could just put the types where we have our parameter names in our info structs, and it would just magically call the C function with the right types.
--
Andrea Faulds
http://ajf.me/

---

## #77055 — Derick Rethans — 2014-09-04T13:32:58+00:00

URL: https://externals.io/message/77053#77055 · In reply to: #77053

> After a long time… back to our fast_zpp RFC.
> 
> Initially Dmitry proposed to have two different APIs, one for the fast version, one for current version:
> #if FAST_ZPP
>     /* new API */
> #else
>     /* old style zend_parse_parameters API */
> #endif
> 
> I don't really like the idea of having two different APIs, so I'd 
> rather propose to use one same public API for both. That API should, 
> depending on some compile-time flag (per file or globally in 
> zend_API.h), either convert to the usual variadic style function, or 
> expand to the new fast variant of API parsing (with directly inlining 
> parameter type specific functions).

I am going to need an ifdef anyway, once for < PHP 7 and once for >= PHP 
7...

> What do you think about having one unified API for both, instead of 
> the current (like it's in some places in master branch currently)? 
> (p.s.: The rewrite of the current API can be done safely via some PHP 
> script I wrote)

I think it makes perfect sense to have two styles. Keep the current zpp 
that we have, and only optimise it with the much less readable versions 
for functions (think `strlen()`) that are called a lot. 

> Also, there is the question about how to structure the API; we (I and 
> Dmitry) basically have now two different proposals:
> 
> 
> ZEND_PARSE_PARAMETERS_START(3, 5)
>     Z_PARAM_ZVAL(regex)
>     Z_PARAM_ZVAL(replace)
>     Z_PARAM_ZVAL(subject)
>     Z_PARAM_OPTIONAL
>     Z_PARAM_LONG(limit)
>     Z_PARAM_ZVAL_EX(zcount, 0, 1)
> ZEND_PARSE_PARAMETERS_END_EX(return);
> 
> OR
> 
> zend_parse_parameters(ZPP_ZVAL(regex) ZPP_ZVAL(replace) ZPP_ZVAL(subject) ZPP_OPTIONAL ZPP_LONG(limit) ZPP_ZVAL_EX(zcount, ZPP_BY_REF), {
>     return;
> })

Both of them very much suck as API compared to:

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|lZ", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {

As I mentioned before, keep the current zpp working, and add a special 
one for the functions where a faster one really matters.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine

---

## #77056 — Dmitry Stogov — 2014-09-04T13:56:59+00:00

URL: https://externals.io/message/77053#77056 · In reply to: #77053

I like the idea of having a single syntax for all cases, but I don't like
the syntax you propose.
In my opinion, it's syntactically inconsistent, less readable and more
error prone, than the old one (sscanf based) and the FAST_ZPP one that is
already in php-master.

I would also prefer to have an ability to select which function should use
"fast" parameter parsing individually.
(You propose use "fast" for all functions, or enable it per extension)
Using "fast" parsing for all functions may significantly increase code size
and slowdown execution, but we won't know it for sure until we didn't try
it.
Anyway, if we find a good single syntax, we must be able to solve technical
problems.

Opinions and other syntax ideas would help us to do our best :)

Thanks. Dmitry.








> After a long time… back to our fast_zpp RFC.
>
> Initially Dmitry proposed to have two different APIs, one for the fast
> version, one for current version:
> #if FAST_ZPP
>     /* new API */
> #else
>     /* old style zend_parse_parameters API */
> #endif
>
> I don't really like the idea of having two different APIs, so I'd rather
> propose to use one same public API for both.
> That API should, depending on some compile-time flag (per file or globally
> in zend_API.h), either convert to the usual variadic style function, or
> expand to the new fast variant of API parsing (with directly inlining
> parameter type specific functions).
>
> What do you think about having one unified API for both, instead of the
> current (like it's in some places in master branch currently)?
> (p.s.: The rewrite of the current API can be done safely via some PHP
> script I wrote)
>
> Also, there is the question about how to structure the API; we (I and
> Dmitry) basically have now two different proposals:
>
>
> ZEND_PARSE_PARAMETERS_START(3, 5)
>     Z_PARAM_ZVAL(regex)
>     Z_PARAM_ZVAL(replace)
>     Z_PARAM_ZVAL(subject)
>     Z_PARAM_OPTIONAL
>     Z_PARAM_LONG(limit)
>     Z_PARAM_ZVAL_EX(zcount, 0, 1)
> ZEND_PARSE_PARAMETERS_END_EX(return);
>
>
> OR
>
>
> zend_parse_parameters(ZPP_ZVAL(regex) ZPP_ZVAL(replace) ZPP_ZVAL(subject)
> ZPP_OPTIONAL ZPP_LONG(limit) ZPP_ZVAL_EX(zcount, ZPP_BY_REF), {
>     return;
> })
>
>
> We'd like to have some discussions about what API to use for the next
> years. If you have some better API, feel free to propose it.
>
> Thanks,
> Bob

---

## #77057 — Pierre Joye — 2014-09-04T14:00:41+00:00

URL: https://externals.io/message/77053#77057 · In reply to: #77056

> I like the idea of having a single syntax for all cases, but I don't like
> the syntax you propose.
> In my opinion, it's syntactically inconsistent, less readable and more
> error prone, than the old one (sscanf based) and the FAST_ZPP one that is
> already in php-master.

I do not like any of the new ones, FAST_ZPP included. I find them all
error prones and not as KISS as what we have now.

As I understand correctly the only reason we have this discussion is
the performance impact of zpp with some functions, mainly
ZEND_FUNCTIONs. What prevents us to make them operators? That may
break things like  call_user_func("strlen", $arg), array_map and the
likes but there may have ways to limit the BC breaks here too. If it
avoid an endless discussion about APIs, it is worse the effort to try
it.

Cheers,
--
Pierre
@pierrejoye | http://www.libgd.org

---

## #77058 — Dmitry Stogov — 2014-09-04T14:02:26+00:00

URL: https://externals.io/message/77053#77058 · In reply to: #77055

> 
>
> > […]
> version, one for current version:
> > […]
>
> I am going to need an ifdef anyway, once for < PHP 7 and once for >= PHP
> 7...
>
> > […]
>
> I think it makes perfect sense to have two styles. Keep the current zpp
> that we have, and only optimise it with the much less readable versions
> for functions (think `strlen()`) that are called a lot.
>
> > […]
> ZPP_ZVAL(subject) ZPP_OPTIONAL ZPP_LONG(limit) ZPP_ZVAL_EX(zcount,
> ZPP_BY_REF), {
> > […]
>
> Both of them very much suck as API compared to:
>
> if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|lZ", &regex,
> &replace, &subject, &limit, &zcount) == FAILURE) {
>

scanf() is suck as well, but I agree, that it makes no sense to switch from
one bad but working solution to another one.


> As I mentioned before, keep the current zpp working, and add a special
> one for the functions where a faster one really matters.
>

This was an original proposal, that is already in php-master, but I
promised that we will discuss it in some point.

Thanks. Dmitry.


>
> cheers,
> Derick
>
> --
> http://derickrethans.nl | http://xdebug.org
> Like Xdebug? Consider a donation: http://xdebug.org/donate.php
> twitter: @derickr and @xdebug
> Posted with an email client that doesn't mangle email: alpine

---

## #77060 — Stas Malyshev — 2014-09-05T01:55:50+00:00

URL: https://externals.io/message/77053#77060 · In reply to: #77057

Hi!

> As I understand correctly the only reason we have this discussion is
> the performance impact of zpp with some functions, mainly
> ZEND_FUNCTIONs. What prevents us to make them operators? That may
> break things like  call_user_func("strlen", $arg), array_map and the

There's also an issue that strlen("foo") may mean a different thing if
you're in a namespace. So there may be a challenge to do this on
compiler level, at least in the obvious way. But maybe there's a way
around it, so theoretically we could make compiler treat `strlen()` as
operator, or, more precisely, as an inline function looking like C
function with parameters passed in registers. I.e., what I mean is
skipping the whole parameter-passing and receiving altogether and just
give it the slot where the variable lives. Of course, it would work only
with `strlen()` and such which do not modify the argument and hardly do
anything with it at all, and strlen would essentially have to have two
implementations - one for "inline" usage and one for "normal" usage
($foo(), `call_user_func()`, etc.). But since 99% of actual usage would be
"inline" it may still be beneficial.

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/

---

## #77063 — Dmitry Stogov — 2014-09-05T06:45:41+00:00

URL: https://externals.io/message/77053#77063 · In reply to: #77060

It's already done for `strlen()` - ZEND_STRLEN opcode (and few other
functions).
But it make no sense to convert all useful functions into opcodes.
We need an ability of fast parameter parsing anyway.

Thanks. Dmitry.



On Fri, Sep 5, 2014 at 5:55 AM, Stas Malyshev <smalyshev@sugarcrm.com>
wrote:

> Hi!
>
> > […]
>
> There's also an issue that strlen("foo") may mean a different thing if
> you're in a namespace. So there may be a challenge to do this on
> compiler level, at least in the obvious way. But maybe there's a way
> around it, so theoretically we could make compiler treat `strlen()` as
> operator, or, more precisely, as an inline function looking like C
> function with parameters passed in registers. I.e., what I mean is
> skipping the whole parameter-passing and receiving altogether and just
> give it the slot where the variable lives. Of course, it would work only
> with `strlen()` and such which do not modify the argument and hardly do
> anything with it at all, and strlen would essentially have to have two
> implementations - one for "inline" usage and one for "normal" usage
> ($foo(), `call_user_func()`, etc.). But since 99% of actual usage would be
> "inline" it may still be beneficial.
>
> --
> Stanislav Malyshev, Software Architect
> SugarCRM: http://www.sugarcrm.com/

---

## #77064 — Pierre Joye — 2014-09-05T07:20:37+00:00

URL: https://externals.io/message/77053#77064 · In reply to: #77063

> It's already done for `strlen()` - ZEND_STRLEN opcode (and few other
> functions).
> But it make no sense to convert all useful functions into opcodes.
> We need an ability of fast parameter parsing anyway.

Got that, but hard to say for which functions. Right now it is used
for almost everything, reflection, pcre, etc. I can hardly think about
why a faster zpp may impact these functions. Do you have an exhaustive
list?

I am not saying it is not good to rethink zpp but if we do then the
gain from a usability point of view must be much better. I do not see
that now (yes, subjective but...).

Cheers,
-- 
Pierre

@pierrejoye | http://www.libgd.org

---

## #77065 — Dmitry Stogov — 2014-09-05T07:40:45+00:00

URL: https://externals.io/message/77053#77065 · In reply to: #77064

most of the functions converted to FAST_ZPP were collected by profiling or
real life apps.
These functions spent significant part of the time in
zend_parse_parameters() because they are short themselves or because they
are called very often.

few functions were added to test some "exotic" type specifiers (like "C" or
"L").

Thanks. Dmitry.




> 
> > […]
>
> Got that, but hard to say for which functions. Right now it is used
> for almost everything, reflection, pcre, etc. I can hardly think about
> why a faster zpp may impact these functions. Do you have an exhaustive
> list?
>
> I am not saying it is not good to rethink zpp but if we do then the
> gain from a usability point of view must be much better. I do not see
> that now (yes, subjective but...).
>
> Cheers,
> --
> Pierre
>
> @pierrejoye | http://www.libgd.org

---

## #77066 — Pierre Joye — 2014-09-05T08:14:29+00:00

URL: https://externals.io/message/77053#77066 · In reply to: #77065

> most of the functions converted to FAST_ZPP were collected by profiling or
> real life apps.
> These functions spent significant part of the time in
> zend_parse_parameters() because they are short themselves or because they
> are called very often.

Ok. So there is no real short list of functions actually needing fast
zpp. I am not sure about the actual impact on pcre or reflection
functions, no matter how often they are called. They are going to be
slower than each anyway, f.e. On the other hands, some standard
functions (each, prev and co) fit in the same area than strlen, no?

Cheers,
-- 
Pierre

@pierrejoye | http://www.libgd.org

---

## #77067 — Dmitry Stogov — 2014-09-05T09:24:21+00:00

URL: https://externals.io/message/77053#77067 · In reply to: #77066

no.

Dmitry.




> 
> > […]
> or
> > […]
>
> Ok. So there is no real short list of functions actually needing fast
> zpp. I am not sure about the actual impact on pcre or reflection
> functions, no matter how often they are called. They are going to be
> slower than each anyway, f.e. On the other hands, some standard
> functions (each, prev and co) fit in the same area than strlen, no?
>
> Cheers,
> --
> Pierre
>
> @pierrejoye | http://www.libgd.org
