On 11 Aug 2014, at 08:36, Dmitry Stogov <dmi...@zend.com> 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

Reply via email to