On 11 Aug 2014, at 08:36, Dmitry Stogov <[email protected]> wrote:
> Hi Andrea,
>
> Could you measure the performance impact of function referencing.
>
> <?php
> $func = "strlen";
> for ($i = 0; $i < 10000; $i++) {
> $func("hello");
> }
> ?>
>
> vs
>
> <?php
> $func = &strlen;
> for ($i = 0; $i < 10000; $i++) {
> $func("hello");
> }
> ?>
On my machine:
andreas-air:php-src ajf$ time sapi/cli/php ../funcref_a.php
real 0m0.043s
user 0m0.022s
sys 0m0.008s
andreas-air:php-src ajf$ time sapi/cli/php ../funcref_b.php
real 0m0.023s
user 0m0.015s
sys 0m0.006s
I think the reason that function references are faster here is that it only has
to do the hash table lookup once. If you tried to create a reference on each
iteration and compared that to just using the string, then the string would be
faster, as no memory needs to be allocated and deallocated for the closure.
> I don't like the "&" syntax a lot, but I understand that it's a compromise
> between readability and implementation complication.
Right. Myself, I’d prefer to just merge PHP’s namespaces and have $foo =
func_name; work, but that wouldn’t work well and would break a lot of things.
>
> The patch probably misses support for "&self::foo", "&parent::foo",
> "&static::foo”.
Good catch, I’ll try and get that implemented. Actually, I wonder if having
&self::foo be bound to the object using it would be a good idea. While I
resisted for &$foo::bar (I don’t support that syntax anyway), there might be
some merit in it after all. If it would bind for you, you could always remove
the binding or change it if it would be a problem.
> It also may be improved using run_time cache (this is not important now).
That’s something I wanted to do (might solve the performance problems with
using & on each iteration), but I’m not sure quite what the right way to
implement that is. In particular, what kind of cache (some sort of hash map?),
how to index it (function name? fully-qualified function name?) and where to
put it. I suppose I could just add a zval pointer to zend_function itself, but
that would add eight bytes to every single function, which would add up.
Actually, on a related note: Currently & creates a new closure on each use, and
in PHP closures are compared by identity, not by their value. Perhaps we should
change that so it checks for the same scope, this_ptr and implementation?
Having &strlen === &strlen would probably be a good thing, it’s the more
intuitive thing at least. Comparing the this_ptr of the two would be easy,
however I have no idea whether you could compare the two zend_functions and
have it work properly. You can’t just do an == in the C code, as closures embed
and modify the zend_function.
--
Andrea Faulds
http://ajf.me/
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php