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_consumptionandopcache.max_accelerated_filesmust fit your whole codebase includingvendor/. Checkopcache_get_status()for a full cache or a poor hit rate.opcache.validate_timestamps=0stops PHP from checking file modification times, which saves syscalls, but then new code is not seen until you reload PHP-FPM or callopcache_reset(). Make that part of every deploy.opcache.interned_strings_bufferholds 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.