TYPO3 v11 requires PHP 7.4 at least. 7.4 introduced Opcache Preloading. We should provide support for it.
What is Preloading: https://www.php.net/manual/en/opcache.preloading.php
Then the question is how to support it. After a tiny bit of research and discussion in Slack, I’ve determined the following:
There is an off-the-shelf Composer package we could pull in and use to generate the preload file: https://github.com/Ayesh/Composer-Preload . It is configured via the composer.json file.
Advantages: It’s already made and we can just use it. Other people use it (per Packagist), too, so it’s likely to stay maintained.
Disadvantages: It uses
opcache_compile_file(), which is sometimes good, sometimes bad. It would probably only work in composer mode. (Which I think is fine.) Each package (or extension) is responsible for determining what should and shouldn’t get preloaded, which is not always ideal.
Symfony built their own mechanism, which also allows Bundles to declare their own preload bits as well as YAML-based configuration (because Symfony). In their case, it’s done via
class_exists()calls in a PHP file referenced by their standard preload builder. We could write something similar.
class_exists()is more robust, if the autoloader is available at the time preloading happens. Symfony sets it up that way, and we could do the same. It would also allow including files that contain just functions with
include_once(). 5.1 also added support for a preload tag in their container configuration, although I don’t know much about it. That may offer some fine-grained control if we want to just steal (yay OSS) whatever their code for that looks like.
Disadvantages: I don’t know that Symfony’s approach is packagable, so we’d be writing our own implementation based on theirs. Not the worst thing in the world, but it would require a command line tool of some kind in core, even if it’s just a one-off script.
An unclear question is who is in the best position to determine what should be preloaded: The extension author or the site owner. Both have good arguments in their favor. From experience, I don’t think “allow both to do anything” is a good idea because then you need some kind of alter event/hook to let the site build process modify what extensions do, or what other composer libraries do, and that gets to a really messy and bug-ridden place very quickly. The most flexible we probably want to get is allowing packages to opt-in files, and allowing a site-specific config to opt-in files, but no way to opt-out files that the package opted in. Making it purely additive keeps it simple.
Any files that are specified in a composer
'files’ autoload list should be preloaded. They’ll be loaded on every request anyway, so may we well preload them and get it over with. There’s probably some way to introspect the composer.lock file and get a list of those, but I don’t know of an existing bit of code for it. I may just have not found one yet. (If so, we should write one as a stand alone component to share.) Note: There might be a caveat on this one with some files, like environment set as some hosts use (eg, Platform.sh). I haven’t experimented with this fully.
As a reminder, this would all be opt-in. I’d recommend it for most sites unless they’re on crappy cheap hosting that share their FPM process with other sites. (Preloading is a bad idea there.) The level of benefit will vary widely, but in most cases it should be at least something.
There are likely other considerations. This isn’t a mandatory feature, but for a codebase this large it seems a good win to get something in place, even if it’s intended to evolve as we get a better sense of what the “best” set of classes to load is.