DEV Community

Cover image for Using OPcache
Guilherme Nascimento
Guilherme Nascimento

Posted on Edited on

Using OPcache

OPcache improves PHP performance by storing pre-compiled code in shared memory, avoiding reading and recompiling for each request. This saves CPU usage and allows the server to handle significantly more simultaneous accesses.

This tutorial shows how to check, enable, configure, and validate OPcache on a production server.

Prerequisites

  • Access rootto or sudofrom the server
  • PHP 7.0 or higher (from PHP 5.5 onwards the extension comes with PHP; in PHP 8.x it is part of the core)
  • Find out which SAPI you are using: PHP-FPM (Nginx/Apache) or mod_php (Apache)

Step 1: Check if OPcache is already active.

php -v
Enter fullscreen mode Exit fullscreen mode

If the output mentions with Zend OPcache, the extension is installed. To confirm if it is enabled:

php -i | grep -i "opcache.enable"
Enter fullscreen mode Exit fullscreen mode

Warning: PHP CLI and PHP-FPM use different configuration files. The result above applies to the CLI. To see what FPM actually uses, see Step 6.

Step 2: Install the extension (if necessary)

Debian/Ubuntu

sudo apt update
sudo apt install php8.5-opcache
Enter fullscreen mode Exit fullscreen mode

RHEL/Rocky/AlmaLinux (Remi repository)

sudo dnf install php-opcache
Enter fullscreen mode Exit fullscreen mode

Replace 8.5with the PHP version you are using.

Step 3: Locate the configuration file.

php --ini
Enter fullscreen mode Exit fullscreen mode

Common places:

Distribution Path (FPM)
Debian/Ubuntu /etc/php/8.5/fpm/conf.d/10-opcache.ini
RHEL/Rocky /etc/php.d/10-opcache.ini

Tip: Instead of editing the default file (which can be overwritten in updates), create your own file with higher priority, for example 99-opcache-custom.iniin the same folder conf.d.

Step 4: Configure OPcache for production.

Create the file:

sudo nano /etc/php/8.5/fpm/conf.d/99-opcache-custom.ini
Enter fullscreen mode Exit fullscreen mode

Recommended content:

[opcache]
; Enables OPcache
opcache.enable=1
opcache.enable_cli=0

; Memory reserved for bytecode (in MB)
opcache.memory_consumption=256

; Memory for interned strings (in MB)
opcache.interned_strings_buffer=16

; Maximum number of cached files.
; Must be greater than the number of .php files in the project.
opcache.max_accelerated_files=20000

; PRODUCTION: do not check if files have changed
; (higher performance; requires clearing the cache on every deployment)
opcache.validate_timestamps=0

; Only relevant if validate_timestamps=1 (interval in seconds)
opcache.revalidate_freq=0

; Prevents memory waste
opcache.max_wasted_percentage=10

; Stores the full file path in the cache
opcache.use_cwd=1
Enter fullscreen mode Exit fullscreen mode

Explanation of the main parameters

Directive Value Reason
opcache.enable 1 Enable cache
opcache.enable_cli 0 In the CLI, the cache does not persist between executions, so it's not helpful (except in long-running workers).
opcache.memory_consumption 256 The standard size (128 MB) is often insufficient for large projects.
opcache.max_accelerated_files 20000 Use a value greater than the total number of PHP files (include the comma vendor/) .
opcache.validate_timestamps 0 Eliminates calls stat()on each request, but requires a cache reset on deployment.

To count how many PHP files your project has:

find /var/www/meuapp -type f -name "*.php" | wc -l
Enter fullscreen mode Exit fullscreen mode

Note: With this approach validate_timestamps=0, changes to files will not appear until the cache is cleared. See Step 7. If you don't already have an organized deployment process, start with this opcache.validate_timestamps=1and other methods opcache.revalidate_freq=60.

Step 5 (optional): Preload (PHP 7.4+)

This opcache.preload=executes an arbitrary file that is run only once during server startup (PHP-FPM, mod_php, etc.) in persistent memory, which can be very useful in the framework.

Inphinit already provides a script for this use, located in system/boot/preload.php which can be edited manually to configure the most used classes in your application, and to use it, simply point to its location as in the example:

opcache.preload=/path/to/my-app/system/boot/preload.php
opcache.preload_user=www-data
Enter fullscreen mode Exit fullscreen mode

If you have a frequently used class, such as a class installed via composer, you can edit it by adding it to system/boot/preload.php, as in the example:

OPcache::preload(array(
    ...,
    Foo\Bar\Baz::class,
));
Enter fullscreen mode Exit fullscreen mode

After modifying the file, it is necessary to restart PHP-FPM.

Experimental: This is an experimental feature being considered for inclusion and may be subject to change or refactoring

Step 6: Restart the service and validate.

Test the configuration before restarting:

sudo php-fpm8.5 -t
Enter fullscreen mode Exit fullscreen mode

Restart:

sudo systemctl restart php8.5-fpm
Enter fullscreen mode Exit fullscreen mode

If you are using Apache with mod_php, the command to restart is:

sudo systemctl restart apache2
Enter fullscreen mode Exit fullscreen mode

Step 7: Clear the cache after each deployment.

With this validate_timestamps=0, the cache needs to be invalidated after each deployment. Options:

Option A: Reload PHP-FPM (the simplest and most reliable)

sudo systemctl reload php8.5-fpm
Enter fullscreen mode Exit fullscreen mode

It reload's a nice feature: workers finish ongoing requests before being replaced, without taking down the service.

Option B: Call opcache_reset()via web request

Create a protected route (for example, accessible only via localhost ) and call it at the end of the deployment:

$app->action('GET', '/opcache/reset', function () {
    if (!in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'], true)) {
        http_response_code(403);
    } elseif (opcache_reset()) {
        return 'OPcache limpo.';
    }

    return 'Falha ao limpar cache.';
});
Enter fullscreen mode Exit fullscreen mode
curl -s http://127.0.0.1/opcache/reset
Enter fullscreen mode Exit fullscreen mode

Remember, opcache_reset()using the CLI does not affect the FPM cache, as they are separate processes and memories.

Problem solving

Symptom Probable cause Solution
Changes to the code are not showing up. validate_timestamps=0no reset Rode systemctl reload php8.5-fpm
opcache_get_status()returns false OPcache disabled in FPM Check out opcache.enable=1the FPM ini file.
Low success rate Cache full Increase memory_consumptionand max_accelerated_files
FPM does not increase after activating preload. Error in preload script Look journalctl -u php8.5-fpm

References

Top comments (0)