Bytecode Caching
It was a conscious decision to make the compilation of PHP source code into PHP bytecode for execution an implicit operation. A PHP developer does not need to think about compilation while he or she is “getting things done”. This implicit compilation step is the reason for the rapid feedback loop PHP developers are so used to. Traditionally, this allowed the developer to alternate between editing the source code and refreshing a page in the browser. Modern best practices like test-driven development replace the browser with executing automated tests.
This rapid feedback loop during development, however, comes with a price that has to be paid in production: PHP source code has to be compiled into PHP bytecode for each request. This is an expensive process that costs time and memory. Moreover, recompiling the same source code over and over again is superfluous. This is where bytecode caching comes into play. A bytecode cache stores the compiled representation of PHP source code and can significantly increase the performance (up to 70% more requests per second).
Implicit compilation combined with bytecode caching gives PHP developers the best of both worlds: quick feedback to frequent code changes during development and fast execution in production.
Since version 4, the PHP interpreter can be extended with bytecode caching capabilities. Over the years, various open source and closed source solutions were made available. PHP 5.5 was the first version of PHP to ship with an out-of-the-box bytecode cache. It is based on the once commercial product ZendOptimizer+, is called OpCache, and shows significant performance improvements over APC (between 5% and 20% more requests per seconds). APC, or Alternative PHP Cache, was the de-facto standard, open source solution for bytecode caching before PHP 5.5 and is no longer maintained.
When you download PHP 7 from https://php.net
and
build the PHP interpreter yourself, the opcache
extension is built – but disabled – by default. If you do not build
PHP yourself and instead use a package provided by the vendor of
your Linux distribution to manage your PHP environment then,
depending on your Linux distribution, you might need to install a
separate package to get the opcache
extension.
Before PHP 7, OpCache was only able to store PHP bytecode in shared memory. This is exactly where you typically want to store the bytecode of your web application. OpCache can optionally store PHP bytecode in the filesystem as of PHP 7. This makes bytecode caching finally available for PHP code that is executed on the command-line. This can, for instance, reduce the execution time of a test suite.
Here is how to set up bytecode caching using OpCache in the PHP
CLI interpreter’s php.ini
configuration file:
opcache.enable_cli=1
opcache.file_cache=/tmp
opcache.file_cache_only=1
With opcache.enable_cli=1
we enable bytecode caching
for the PHP CLI interpreter. Using the
opcache.file_cache
directive we configure the path to a
directory in which the cached bytecode will be stored. This
directory must exist and should be on a RAM disk (mounted using
tmpfs
, for instance). The
opcache.file_cache_only
directive configures OpCache to
exclusively utilize the filesystem-backed cache. This bypasses the
shared memory storage which is useless on the command-line.
The filesystem-backed cache may also be useful for deploying the
compiled bytecode representation of PHP applications to one or more
web servers in certain situations. The deployment process would then
start off by compiling the *.php
source code files into
*.php.bin
files. These can then be packaged into an RPM
package, for instance, for distribution to and activation on the web
server(s).