Nicolas Grekas
Contributed by Nicolas Grekas in #32032

PHP 7.4 was released a few days ago and it's the most exciting PHP release in years. It includes game-changing features such as typed properties, arrow functions, covariant types, FFI (Foreign Function Interface), OPCache preloading and more.

OPCache Preloading

At the very beginning, PHP parsed and compiled any file used to serve a request. The parsing/compiling result (called "opcodes") was not reused for other requests, so the exact same process had to be repeated again and again.

On production servers, the code of your PHP files does not change between requests, so the parsing and compiling result can be reused. That's what the OPCache does (OPCache = "opcodes cache"), improving the overall performance between 2 and 15 times.

However, the OPCache doesn't remove other execution costs: PHP still has to check if the source file was modified, copy certain parts of classes and functions from the shared memory cache to the process memory, etc. Moreover, since each PHP file is compiled/cached completely independently from any other file, PHP can't resolve dependencies between classes stored in different files and has to re-link the class dependencies at run-time on each request.

PHP 7.4 can eliminate most of these costs thanks to preloading. On server startup - before any application code is run - PHP can load a certain set of PHP files into memory and make their contents permanently available to all subsequent requests.

All the functions and classes defined in these files will be available to requests out of the box, exactly like internal entities (e.g. strlen() or Exception). In fact, PHP can preload entire or partial frameworks like Symfony, and even the entire application class library.

OPCache Preloading in Practice

Preloading is controlled by a new php.ini directive called opcache.preload. The value of this directive is the path of the PHP file that preloads the files using either include_once or opcache_compile_file().

During preloading, PHP also resolves class dependencies and links with parent, interfaces and traits. It also removes unnecessary includes and performs some other optimizations. The overall result is a performance improvement of 30%-50% in real applications.

Keep in mind that preloaded files remain cached in OPCache memory forever. If you change the source code of any preloaded file, you'll need to restart the web server or changes won't have any effect.

OPCache Preloading in Symfony

Thanks to the internal Symfony behavior of compiling files before running the application (e.g. the service container) we can introduce support for preloading with only a few changes. That's why Symfony 4.4 can generate a preloading file for your application in the cache directory. The generated file name includes both the environment and kernel names (e.g. var/cache/dev/App_KernelDevDebugContainer.preload.php).

You can use this generated file as the value of the opcache.preload PHP directive:

1
2
; php.ini
opcache.preload=/path/to/project/var/cache/prod/App_KernelProdContainer.preload.php

The next step will be to allow applications and bundles to declare which of their classes should be preloaded too. Check out the Pull Request #33689 to see the work in progress feature to do that.

If you are already running PHP 7.4, please test this feature in your real projects and report the performance improvement. Or even better, publish a blog post with the details and we'll feature it in the next A Week of Symfony post.

Published in #Living on the edge