PHP 7.4 is the latest version of the PHP programming language that will launch later this year. PHP 7.4 recently went into beta, so I started exploring the new features. One feature showing a lot of promise is called Opcache Preload. Using preload you can set PHP to load certain PHP files into memory on startup. Doing so reduces the amount of files PHP has to compile when receiving an HTTP request which improves performance. Before exploring preload, let us look at how opcache works in the PHP runtime.
In PHP, the term PHP is used for the programming language. However, the runtime that executes PHP code is called the Zend Engine. When the Zend Engine receives a request for a PHP file, it actually compiles the PHP file into a list of operation codes, hence the term
opcache Zend Engine extension stores those opcodes in memory after a PHP file is compiled, so that the PHP file does not have to be compiled again in subsequent requests for the file.
opcache.preload directive allows a PHP programmer to instruct the opcache to cache the opcodes for a set of PHP files when the Zend Engine is activated. The preload option should be pointed to a PHP file that runs the function
opcache_compile_file on the files you want preloaded.
To use preloading, you have to install PHP 7.4. I am using Ubuntu WSL on Windows with the ondrej/php PPA activated. Since I'm using Ondrej's PPA, I can run
sudo apt install php7.4-fpm in bash to get the latest 7.4 beta on my system. I use the FPM installation with Nginx as my web server and a host entry called
preloading.local pointed at my project. After installation, I opened the FPM php.ini file (located at
/etc/php/7.4/fpm/php.ini on my system) and changed the
opcache.preload option to the path to my
preload.php file in my project.
preload.php file uses a modified
preload function based on Dmitry Stogov's example in the Preload RFC. I have all the Slim dependencies loaded in a
vendor folder using Composer. I then use the
preload function in my
preload.php on all the Composer source files I need to run the Slim application. After restarting PHP FPM (
sudo service php7.4-fpm restart), I can open
preloading.local in my browser and see my application run successfully.
- I like that I did not have to use the Composer autoloader for my framework. Since all of the framework code was preloaded, autoloading is unnecessary. I do hope that Composer will generate an automatic
preload.phpfile, like the
autoload.phpfile, so that vendor dependencies can be preloaded easily.
- The performance gain is miniscule for a small project like this one, however, I can see preloading being a great way to speed up large frameworks like Symfony, Laravel and especially Magento.
- Preloading will be tricky to implement if you have multiple PHP projects on the same server, since you can only set one file to be preloaded.
- I had an issue where preloading would not load the
functions.phpfile in the
nikic/fast-routemodule because it was wrapped in an
ifstatement. I had to set up a patch file to manually load those functions without the
ifstatement. It is probably because 7.4 is still in beta or my
preload.phpneeds to be improved.
- I do not think many PHP developers will use preload in development environments. I generally am reluctant to use features in production that are unused in dev because of the potential for unseen issues to arise on production servers. However, the risk is pretty low for preloading, so it will still be worth it to have it enabled.
All in all, I'm really looking forward to the performance gains from preloading. PHP is already one of the fastest scripting languages on the web and I am happy that the core team continues to push PHP into faster territories.