[RFC] Opache Preloading for Mezzio and MVC

Goal

Provide a mechanism for seeding the opcache preloading capabilities of PHP for:

  • MVC and API Tools applications
  • Mezzio applications

Background

PHP 7.4 introduces the opcache.preload setting and the opcache_compile_file() function. These can be used to preload files into the OpCache prior to starting the background PHP process (whether thats mod_php, php-fpm, or something like Swoole).

To use the functionality, you must define a file that performs include operations on the various files you want preloaded, or which calls opcache_compile_file() on each.

One thing to note: when compiling a file containing a class, you must also make certain you compile anything on which it depends: interfaces, parent classes, traits, etc. Failing to do so will result in a failure to preload its data.

Considerations

  • Since the functionality is compiling opcodes and storing them in memory, there’s obviously a trade-off in the amount of memory used. One thing to note is that if this goes beyond a certain threshold, you lose some efficiency; the common understanding is that the number of classes preloaded should likely not exceed around 100.

  • We currently compile configuration on first-request and then cache it. Additionally, it’s an array. We should likely provide some mechanism for compiling it to an ArrayObject implementation which can be autoloaded or included somehow.

    • Keep in mind that such configuration will likely need access to environment variables, and, as such, would need to be a deployment-time operation. When you consider Docker containers, this is a simple problem to solve, as env variables are passed as the container spins up, and the opcache.preload file is loaded when the PHP process starts. (This is how platform.sh works as well.)
  • It might be useful to be able to create a “compiled container”, based on the compiled configuration.

Suggested Approaches

One suggested approach is to generate a preload file that contains a class whereby you can specify directory paths with class files to include, and which uses the generated composer classmap autoloader to determine if a given file is relevant for purposes of providing PHP classes. Such a class can then also be used to provide a list of classes to ignore (e.g., if there are adapters you are not interested in).

If we went this route, we could even provide sane defaults for libraries you may want to preload: mezzio/mezzio, laminas/laminas-mvc, etc.

An example of such a class can be found on stitcher.io.

This would require:

  • Command line tooling
  • that would generate the preload file.
1 Like