Cache Information Upgrade

By Jérôme Vieilledent, on Jul 17, 2020

Blackfire gives you visibility on how your application behaves. However, the interaction between functions is not the only thing that could affect your application performance.

Your app indeed usually runs over an engine based on the language you use (e.g. PHP, Python…), which can also be fine-tuned to provide the best possible performance, especially when it comes to internal cache mechanisms.

PHP Caches and their Purposes

PHP has a collection of internal cache mechanisms which serves different purposes. Some are purely internal and other are provided by extensions.

Realpath cache

In this cache, PHP stores the full path to the files your application uses. Keeping these locations in cache avoids multiple expensive lookups (i.e. stat calls) to the filesystem. The default value is 4M as of PHP 7.0.16, which is usually more than enough.

It is configurable with the realpath_cache_size setting in php.ini

PCRE cache

This cache keeps regular expressions in memory, in order to avoid evaluating them.

This cache is not configurable.

APCu

This PHP extension provides a key/value store within the PHP engine itself. It can be used for application cache (e.g. using Symfony Cache Component), or to optimize Composer autoloader.

OPCache

This PHP extension, which is part of the core as of PHP 5.5, optimizes and caches opcode generated by PHP. It is always recommended to have it enabled, and mandatory for production servers. Putting it simple, it avoids recompiling PHP files by caching the result in a shared memory (aka shm).

It also provides a few candies 🍬 like the Interned Strings Buffer.

Behind this cryptic name lies a fundamental and powerful cache, as in this buffer, OPCache stores every immutable strings of your application (including annotation comments), and that makes a lot of strings!

Each string is linked to a pointer, which is then reused whenever possible.
Actually, the Interned Strings mechanism has been there for a long time in PHP (since PHP 5.4.0), but the pointers were not shared between processes. OPCache adds a buffer over it, so that the pointers can be shared between PHP-FPM workers.

Learn more about Interned Strings Buffer in the awesome article by Julien Pauli.

Blackfire Providing Cache Information

In every profile, Blackfire provides a summary of all these caches. Always keep an eye on those level gauges and ensure to dimension them enough. We usually consider that a cache buffer should be filled up more than 85%.

Recent Improvements with OPCache

In some cases, OPCache can lead to unexpected behaviors, leading to very slow requests. This is usually due to the OPCache restart mechanism, and means that you should tweak your configuration.

OPCache shared memory consumption should not grow that much when it is well dimensioned. However when a script changes OPCache doesn’t free the buffer. It marks the stale script as wasted. This happens because of the recompilation of the modified PHP files, e.g. when you deployed new ones, or because your application has generated other PHP files.

In such cases OPCache can restart in order to purge its shared memory. The problem is that it can be very costly in terms of resources consumption, and thus performance!

To avoid confusions, we recently added information about OPCache restarts:

It usually happens when OPCache runs out of shared memory. Rule of thumb: Never run out of OPCache shared memory!

Remember that whenever you change files, OPCache will recompile them and mark the previous ones as /wasted/, making the shared memory grow.
At some point, defined by the opcache.max_wasted_percentage setting, OPCache will restart.

To avoid this, we recommend to follow the suggestions made by Julien in his article:

  • Turn off revalidation mechanism on production (turn opcache.validate_timestamps to 0)
  • Correctly size your buffers (opcache.memory_consumption, opcache.interned_strings_buffer, opcache.max_accelerated_files

Play with the demo or subscribe now!

Happy profiling, but keep an eye on Cache Information 😉!

Jérôme Vieilledent

As a Developer Advocate, Jérôme is all about spreading the love! His technical/development background enable him to talk as a peer to peers with our developer users. You’ll read his tips and advices on performance management with Blackfire. And he’ll support you as a day-to-day user.