Re: Optional pre-compiler for PHP8?
| From: | Andreas Hennings | Date: | Mon, 28 Oct 2019 03:33:37 +0000 |
| Subject: | Re: Optional pre-compiler for PHP8? | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-107717@lists.php.net to get a copy of this message | ||
On Mon, 28 Oct 2019 at 01:33, Benjamin Morel <benjamin.morel@gmail.com> wrote:
>
> >
> > > So we'd probably need some built-in definition of a "package", which
> > could be analysed and compiled as one unit, and didn't rely on any run-time
> > loading.
> > That idea of a "package" came up during a debate on this list at least
> > once, a few months ago, and I think it makes a lot of sense. And what I
> > proposed effectively implies that namespaces would be treated like packages
> > from the perspective of the compiler.
>
>
>
> Putting aside the idea of distributing pre-compiled PHP scripts, if we're
> only debating the precompilation as, notably, a means to reduce the cost of
> type checks, I wouldn't mind if the precompilation occurred *only if
> preloading is in use*, i.e if most class definitions are known on server
> startup, which is when the compilation / optimization passes could occur.
> No preloading = no such optimizations, I could personally live with that.
>
> No need for a package definition, IMO.
This would break as soon as we have two versions of a class, and a
runtime choice which of them to use.
(see also Mark Randall's comment)
What about this, instead:
- Instead of a cli command, lazily "compile" in the opcache. So more
or less what we are already doing, I guess.
- Possibility to store/cache multiple versions of a file, depending on
other files it depends on.
Somehow like this, per file:
1. Compile a low-level version of the file, or load it from a cache,
with cache id = file path.
2. Recursively process all the files and classes (autoload) this file
depends on.
3. Generate a hash from the dependencies.
4. Compile the final version of the file, or load it from a cache,
with cache id = file path + dependencies hash.
Perhaps this could even be further optimized with some "guessing":
Assume everything is as it was the last time, until we hit a conflict.
This is probably more complicated than I am describing it here.
I kept the term "dependencies" intentionally vague, because I am not
sure what exactly we would need to look at.
Perhaps we would store not just multiple versions of each file, but of
each global symbol (class, function).
- One "base version" for each distinct definition of a symbol in a
distinct file.
- One "specific version" per combination of versions of other symbols
this depends on.
One problem I see is that some of the dependees may be unknown at the
time a file is included.
E.g. a function might call a static method from a class that has not
yet been included, triggering the autoloader.
Since the autoloader can be anything, we have no way to predict which
file will be included, and thus, which version the static method to
typecheck against.
Even if we previously scanned the entire project directory, and found
only one class with the given static method, the autoloader might
instead include a file outside the project directory, or define the
class with eval() or stream wrappers, or dump a generated file in
/tmp.
This would mean we would have to run a non-deterministic model until
all dependees are included.
So perhaps this idea is a dead end :)
-- Andreas
>
> — Benjamin
>
> On Mon, 28 Oct 2019 at 00:56, Mike Schinkel <mike@newclarity.net> wrote:
>
> > > On Oct 27, 2019, at 7:04 PM, Rowan Tommins <rowan.collins@gmail.com>
> > wrote:
> >
> > Thank you for your comments.
> >
> > > I chose the phrase "static analysis tool" deliberately, because I wanted
> > to think about the minimum requirements for such a tool, rather than its
> > long-term possibilities.
> >
> > Your points are all well-considered.
> >
> > To be clear, I wasn't stating the idea as a alternative to your idea, I
> > was only stating that your comments inspired me to have the idea of a
> > pre-compiler.
> >
> > IOW, I saw no reason both could not be done, one sooner and the other
> > later.
> >
> > > However, combining those usefully may not be that easy.
> >
> > Also for clarity, I was not assuming existing OpCache would be 100%
> > unmodified, I was talking about benefits that a pre-compiler could have and
> > was less focused on ensuring it could slot into an existing OpCache
> > implementation as-is.
> >
> > IOW, if it is worth doing it might be worth extending how the OpCache
> > works.
> >
> > > So we'd probably need some built-in definition of a "package", which
> > could be analysed and compiled as one unit, and didn't rely on any run-time
> > loading.
> >
> > That idea of a "package" came up during a debate on this list at least
> > once, a few months ago, and I think it makes a lot of sense. And what I
> > proposed effectively implies that namespaces would be treated like packages
> > from the perspective of the compiler.
> >
> > But then again a new package concept might be needed in addition to
> > namespaces, I am not certain either way.
> >
> > > Unlike P++, Editions, or Strict Mode, this would undeniably define that
> > the deprecated features were "the wrong way".
> >
> > I am not sure I cam agree that it would define them as the "wrong way."
> >
> > The way I would see it is there would be a "strict way" and an "unstrict
> > way." If you prefer the simplicity of low strictness and do not need
> > more/better performance or the benefits of type-safety that are needed for
> > building large applications, then the "right way" would still be the
> > "unstrict way."
> >
> > And the non-strict features would not be "deprecated" per-se, they would
> > instead be disallowed for the strict (compiled) way, but still allowed for
> > the unstrict (interpreted) way.
> >
> > > If the engine had to support the feature anyway,
> >
> > I think we are talking two engines; one for compiling and another for
> > interpreting. They could probably share a lot of code, but I would think
> > it would still need to be two different engines.
> >
> > > I'm not sure what the advantage would be of tying it to "compiled vs
> > non-compiled", rather than opting in via a declare() statement or package
> > config.
> >
> > The advantage would be two-fold:
> >
> > 1. Backward compatibility
> >
> > 2. Allowing PHP to continue to meet the needs of new/less-skilled
> > programmers and/or people who want a more productive language for smaller
> > projects that do not need or want all the enterprisey type-safe features.
> >
> > Frankly it is this advantage which is the primary reason I though to send
> > a message to the list. The chance to have the benefit of strictness and
> > high performance for more advanced PHP developers while still having full
> > BC for existing code and for beginner developers seemed highly compelling
> > to me.
> >
> > -Mike
> >
> >