New in Symfony 4.4: Preloading Symfony Applications in PHP 7.4
December 5, 2019 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
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.
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
@Youssef : you will have to restart (not only reload) the web server check the PHP rfc : https://wiki.php.net/rfc/preload
Results here: https://ezplatform.com/blog/benchmarking-php-7.3-vs-7.4-with-symfony-4.4-trouble-with-opcache-preloading
`opcache.preload_user=www-data`
You can use this generated file as the value of the opcache.preload PHP directive:
; php.ini
opcache.preload=/path/to/project/var/cache/prod/App_KernelProdContainer.preload.php
"""
How does one generate that file? It does not appear to be generating automagically for me in v5.0.2. Or was this strictly for Symfony 4.4?