Re: Introducing compile time code execution to PHP p reloading
| From: | Larry Garfield | Date: | Wed, 15 Jan 2020 00:50:57 +0000 |
| Subject: | Re: Introducing compile time code execution to PHP p reloading | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108135@lists.php.net to get a copy of this message | ||
On Tue, Jan 14, 2020, at 1:22 PM, Mike Schinkel wrote:
> On Jan 14, 2020, at 1:10 PM, Larry Garfield <larry@garfieldtech.com> wrote:
> >> I get your concern about recursion, but if that kind of issue is really
> >> a concern I don't see why we could not artificially limit recursion on
> >> preload to a configurable amount, with 100 being the default?
> >
> > It's not recursion itself that's an issue. It's that the behavior of the
> > code changes between preload and non-preload contexts in subtle, non-obvious ways.
> >
> > I don't mean a recursive function that runs during preload. I mean if a function
> > that runs in a normal request is written recursively, it will fail at high recursion levels only if
> > the file it is in was not preloaded. So whether or not foo.php was run through
> > opcache_compile_file() changes when and how code in that file will fail. That's the situation
> > we want to avoid like the plague, IMO.
>
> With respect, that feels like you are concerned about some real edge
> cases, and ignoring the probability that most code run during
> preloading would be written bespoke for preloading.
I think you're still missing my point here. AST manipulation during preload would exist to
manipulate code that would be run *later*. That's the point. Sure, the code in the
run_once/preload/whatever block would be written to run in that context, but its entire point is,
presumably, to improve the running of the *rest* of the code later.
That's where the footgun exists. The recursion example was simply to demonstrate that even
seemingly "safe" optimizations may introduce inconsistency, so I don't expect most
userland developers to be able to get it right the first 5 times. (And again, I include myself in
that.)
> ALSO, I think I may have caused confusion by calling it "preloading."
> In my mind that meant "run once" vs. "run for each page load" but I
> think you are (rightly) conflating what I have called "preloading" with
> the new preloading feature in PHP 7.4?
>
> What I have been envisioning is a
preload (or some other)
> keyword
> that we could apply to functions, methods, and expressions. When
> preload modified functions/methods/expressions are reached
> during
> OpCode generation, rather than generate a call to runtime code PHP
> would just run the code and then take the return value and generate
> OpCode for that return value.
That... is a completely different thing, yes, that has nothing to do with the PHP 7.4 feature called
preloading. Which would mean we've been talking about two different things this whole damned
time. *sigh*
> > That... sounds a lot like the new FFI extension? Write code in C or Rust or anything that
> > can produce a .so file, plug it into PHP, go?
>
> Unless I am misunderstanding, using an .so requires a sysadmin to add
> an extension and update php.ini. Which is a non-starter on hosted sites
> like Pantheon, WPEngine, Kinsta, Pagely, Flywheel, PressLabs and
> similar.
No, the whole point of the FFI extension is that a user-land developer can load a .so file into PHP
directly; basically doing the lib->PHP glue code in PHP rather than in C. It does require the
FFI extension itself to be enabled, and to do safely requires using the preloader, which does mean
setting an ini setting.
Not all hosts support that. The one I work for does, which is why I've been playing with it
lately to document it all for our customers. :-) But the fact that such advanced features are not
universally available is... exactly why I am extremely cautious about having functionality that
results in subtle behavioral differences between those environments where it's available and
those where it's not.
The existing preload logic has no impact on behavior other than skipping the autoloader. Any
behavioral change is limited to those oddball libraries that do black magic during the autoloader,
which are already well off the beaten path. That makes it a "safe" optimization.
My underlying point, and then I will bow out of this thread as I am tired of repeating myself, is
that I am all for enabling more "safe" optimizations, even letting userland developers
build them, but we need to be extremely careful about them being "safe" and not "a
time bomb that will introduce subtle behavioral differences between different run modes that a
developer is not expecting, thus slowly creating libraries that will only function in one run mode
or the other".
If we can enable more optimizations while avoiding that trap, I'm all for it. But avoiding
that trap is more important than giving developers more foot-guns.
--Larry Garfield