PHP define() terribly slow?

I was profiling one of my favorite large PHP applications today using APD. I kept getting what seemed to be strange results -- it was telling me that bunch of defines statements (30+ of them) were responsible for an inordinately large percentage of the page generation time. On minimal pages it was as much as 37%. Even on the well-known largest of pages, they were still clocking in at a not insignificant 5%.

That just didn't seem possible.

So I wrote a bunch of variants on just straight timings of define('X', y) versus $X = y to get some purer comparisons. This was easier said than done.

PHP appears to be smart about setting a variable to the same constant again. Even without that, define() is doing something a bit different in that it is creating a global symbol in PHP's symbol table, whereas setting a new value in an existing variable only has to do an assignment; the creation of the variable happens the first time.

I tried using unset() to force new creation of the variable on each pass through my timing loops, but clearly I was distorting the results by the time used by the unset() calls. But even with that wasted time, variable assignments were about 3 times faster than using define().

With some more fiddling with the code, I was able to factor out the unset() time.

The end result was that setting a variable is nearly 8 times faster than defining a constant.

This was based on 50,000 iterations through a loop defining 30 different constants each pass, versus 50,000 iterations through a loop setting 30 different global variables.

Somehow, this doesn't seem right. If someone can show me where I'm wrong, I'd be glad to see it. Otherwise, I think there's some optimization opportunities out there, both in existing PHP code, and in the C code comprising the PHP runtime.

Comments

I've seen this before, too.

I've seen this before, too. I work with a high-traffic site hosted on a Mac OS X Server box and when I used APD I noticed the same patterns. Arto's Boost module came in real handy to mitigate that. I tried several versions of PHP, both major versions as well as compilations, including compiling my own. Not sure if it's an OS X thing -- that what you're using, by any chance?

Debian Linux

Actually, I was using Debian Etch Linux with PHP 5.2.0-8etch9, Zend Engine v2.2.0, and APD v0.9. I don't think we can blame Mac OS X for this. We've got some RHEL servers, too. Maybe I can try it there.

PHP is not compiled.

PHP is not a compiled language where a pre-processor deals with macro statements. So naturally a define requires a lot of logic from a parser to determine what it is where a variable is clearly specified with $ and the parser doesn't need to waste time figuring out what it is.

Maybe with roadsend defines could be fast... at least the potential is there