zendtech / ZendOptimizerPlus

Other
914 stars 142 forks source link

Strlen pass: `strlen($name) > 49` -> `isset($name[49])` #201

Closed staabm closed 9 years ago

staabm commented 9 years ago

There are some interessting profiling results of the owncloud guys, see quote below. Is this something which could be achieved while at opcode compilation?

In the first iteration the request time went down to 10 minutes by reducing the SQL queries by a factor of 10. Now, another interesting bottleneck showed up: the PHP method strlen was called over 60,000 times by a component from a third party library that ownCloud uses, ZendSearch, from Zend Framework. Focus moved to this library and it became clear that strlen was used to just decide if a string has a defined length. Somebody came up with the idea of simply using the native language construct isset rather than a function like strlen. Instead of doing this...

if (strlen($name) > 49) {
    ...
}
... you can do this which results in the exact same behavior, except that it is a lot faster:
if (isset($name[49])) {
    ...
}

... The change from strlen to isset turned out to also be relevant in ownCloud code, bringing a nice 20% increase in speed for processing a million path lookups.

Quote from http://blog.blackfire.io/owncloud.html

//cc @laruence @dstogov @jpauli

jpauli commented 9 years ago

I have explained this optimization lots of time. If you read my slides at http://fr.slideshare.net/jpauli/quick-tour-of-php-from-inside , starting from slide 59 and follow, you'll have an idea.

We cannot do anything in opcache for this, as your variable is "variable", we can't assume at compile time that it will be a string.

dstogov commented 9 years ago

This optimization may be applied only if $name is string. Unfortunately, in general, we don't know the possible types of $name.

On Wed, Jan 21, 2015 at 11:14 PM, Markus Staab notifications@github.com wrote:

There are some interessting profiling results of the owncloud guys, see quite below. Is this something which could be achieved while at opcode compilation?

In the first iteration the request time went down to 10 minutes by reducing the SQL queries by a factor of 10. Now, another interesting bottleneck showed up: the PHP method strlen was called over 60,000 times by a component from a third party library that ownCloud uses, ZendSearch, from Zend Framework. Focus moved to this library and it became clear that strlen was used to just decide if a string has a defined length. Somebody came up with the idea of simply using the native language construct isset rather than a function like strlen. Instead of doing this...

if (strlen($name) > 49) { ... } ... you can do this which results in the exact same behavior, except that it is a lot faster:

if (isset($name[49])) { ... }

Quote from http://blog.blackfire.io/owncloud.html

— Reply to this email directly or view it on GitHub https://github.com/zendtech/ZendOptimizerPlus/issues/201.

staabm commented 9 years ago

Thanks for your fast replies. Will have a look at those slides to get a better idea of what the opcache can do.

rlerdorf commented 9 years ago

The main thing you have to keep in mind when you think about opcode caching is that it happens at compile time, not runtime. So any optimizations we do to the opcodes will not have the runtime context which in a loosely typed language means we don't know the exact type of a variable.