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