Hi Dmitry, ----- Original Message ----- From: "Dmitry Stogov" Sent: Sunday, July 27, 2008
> Hi Matt, > > At first as you are a scanner expert, I would like you to look into > another optimization idea. > > Probably for historical reason PHP supports shebang lines > (#! /usr/bin/php) on top of php files. Especially to handle them PHP > (CGI/FastCGI/CLI) opens file and check for it. So even with opcode > caches FastCGI PHP does open syscall for the requested script, however > with opcode caches it's absolutely useless. > > In case PHP scanner will handle shebang lines itself, we will able to > save this syscall. Sorry, but now I'm the one who's confused here, since I have no idea what I'm supposed to look into exactly. :-/ I know about shebang lines, and I know there's a check in the scanner now to skip over it (must have been somewhere else with flex...). PHP itself doesn't "use" the shebang, does it? I don't have much knowledge of *nix system stuff, but I thought the shebang is for the OS to use when asked to run an executable script... So I don't understand what could be changed in the scanner to save the open syscall -- since if the scanner is called, the file has already been opened, right? Again, sorry, but I'll need more explanation. :-) > I never had time and enough flex/re2c knowledge to implement this idea > myself. May be you'll able to look into the problem. In case you find a > simple solution we will able to do it in php-5.3. > > Most PHP hosters and large sites use FastCGI with opcode caches (it is > also the primary way for MS Windows users), so this optimization is > really important. > > [see below] Yes, more reply below... > Matt Wilmas wrote: > > Hi Dmitry, > > > > I saw that you commited this patch, with the addition of only replacing > > persistent constants (just mentioning for others on the list). The attached > > patches have a few tweaks: > > > > The main thing I noticed is that if "something" creates a persistent, > > case-INsensitive constant (any of those in "standard" PHP, besides > > TRUE/FALSE/NULL?), it could still wrongly be substituted. My change > > eliminates that possibility. > > After yesterday's subbotnik I'm so stupid so cannot understand simple > tings. :) > Could you point me into the exact part of the patch. Sure, I'll explain more. If something (extension, etc...) creates a persistent constant "foo" and it does NOT have the CONST_CS flag, and capital "FOO" or whatever is used in a script (and a case-sensitive version doesn't exist, of course), it will be lowercased, as you know, and "foo" will be found, but that can't be used since a case-sensitive version may be defined later (TRUE/FALSE/NULL are exceptions, but OK to do since they have CONST_CT_SUBST). Current zend_get_ct_const() behavior after finding case-insensitive "foo": if ((c->flags & CONST_CS) && ...) { efree(lookup_name); return NULL; /* Doesn't fail for "foo" since CONST_CS isn't set... */ ..... if (c->flags & CONST_CT_SUBST) { return c; /* This doesn't happen since CONST_CT_SUBST isn't set... */ } if ((c->flags & CONST_PERSISTENT) && ...) { return c; /* This DOES happen since CONST_PERSISTENT is set */ } The last part is the problem, of course. Substitution should only be done for ones that have: CONST_CT_SUBST or CONST_PERSISTENT and whose case matches that used in the script (CONST_CS or lowercase is used, e.g. "foo" in script is OK, not "FOO" or "Foo") (BTW, that also implies that CT_SUBST is only useful for case-insensitive constants (like T/F/N) and if something sets it with (CS | PERSISTENT), it doesn't really do anything -- except not allow it to be used in "const ..." declarations. :-P Though that could be desired, by something, and/or to also have substitution even in a namespace.) With my change, after finding case-insensitive "foo": if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) { efree(lookup_name); return c; /* Happens for TRUE/FALSE/NULL */ } } efree(lookup_name); return NULL; /* Happens for "foo" before persistent check */ Hope that wasn't TOO verbose. :-O I just swapped the logic (succeed vs fail) of that top part so the else { } block could be removed. > > Checking Z_TYPE(c->value) != IS_CONSTANT[_ARRAY] isn't needed with the > > persistent check now, is it? > > I think you are right, but it's better to have this checks, because > nobody prohibit to create array constants in extensions. OK. :-) > > From orginal patch (zend_constants.c part), the memcmp(...) != 0 isn't > > needed as it will always be true. If it wasn't, the *first* hash lookup > > wouldn't have failed. :-) Like I said in the original message, it's old > > code from a long time ago, but was never removed... > > I'll check it with more clear head. I looked through the CVS logs/versions for zend_constants.c again, and the memcmp() was needed before v1.40 (6 years ago). That's when all constants were lowercased first, and then case was checked. 1.40 added case-sensitive lookup first: memcmp() no longer necessary, as I said. And this old code was then copied to zend_get_ct_const(), etc. That code area shouldn't get hit very often or anything, but might as well remove since it's redundant! :-) > Thanks. Dmitry. - Matt -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php