OPcache, preloading and the JIT

PHP · Expert · 14 min

OPcache is the single biggest PHP performance setting, and misconfiguring it causes stale-code deployments.

PHP compiles each file to opcodes before running it. OPcache stores compiled opcodes in shared memory, so later requests skip parsing and compilation. It should always be on in production (opcache.enable=1); it's typically a several-fold speedup.

Important settings:

  • opcache.memory_consumption and opcache.max_accelerated_files must fit your whole codebase including vendor/. Check opcache_get_status() for a full cache or a poor hit rate.
  • opcache.validate_timestamps=0 stops PHP from checking file modification times, which saves syscalls, but then new code is not seen until you reload PHP-FPM or call opcache_reset(). Make that part of every deploy.
  • opcache.interned_strings_buffer holds deduplicated strings like class and method names.

Preloading (opcache.preload, PHP 7.4) runs a script at server start that loads chosen classes into memory permanently, so they are linked once instead of on every request. Gains are modest for most apps, and any change requires a full restart.

The JIT (PHP 8.0) compiles hot opcodes to machine code. Enable it with opcache.jit=tracing and a non-zero opcache.jit_buffer_size. It speeds up CPU-bound work such as math, image processing or parsers dramatically, but typical web requests spend their time waiting on databases and the network, so the gain there is small. Always benchmark your workload before and after.

opcache.enable_cli is off by default, as one-off CLI scripts rarely benefit.

Example

; php.ini production excerpt
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=50000
; deploys must then reload FPM or call opcache_reset()
opcache.validate_timestamps=0
opcache.preload=/var/www/app/preload.php
opcache.preload_user=www-data
; JIT: helps CPU-bound code
opcache.jit=tracing
opcache.jit_buffer_size=64M

; check from PHP:
;   $s = opcache_get_status(false);
;   $s['opcache_statistics']['opcache_hit_rate'];   e.g. 99.9
;   $s['memory_usage']['free_memory'];

Remember

  • OPcache caches compiled opcodes in shared memory and must be on in production
  • With validate_timestamps=0, every deploy needs an FPM reload or opcache_reset
  • The JIT pays off for CPU-bound code, much less for I/O-bound web requests

Watch out for

  • Setting validate_timestamps=0 and deploying without reloading PHP, so old code keeps running.

Check yourself

  1. A deploy copies new files but users still see old behaviour. OPcache has validate_timestamps=0. What fixes it?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.php.net/manual/en/opcache.configuration.php

Builds on

Unlocks

Nothing builds on this yet.