| name | php-opcache |
| description | Use when optimizing PHP application performance or configuring OPcache: sizing memory and cache limits, tuning revalidation strategy, enabling JIT compilation, setting up preloading, or diagnosing cache saturation and unexpected behavior in production. |
PHP OPcache
OPcache stores precompiled script opcodes in shared memory, eliminating parsing overhead on every request. Misconfiguration leads to silent cache misses, full-cache restarts, or stale code in production.
Production Config (Starting Point)
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.jit=tracing
opcache.jit_buffer_size=64M
opcache.file_cache=/var/cache/php/opcache
See production.md for reasoning, gotchas, and monitoring.
Files in This Skill
| File | Contents |
|---|
| configuration.md | Complete directive reference — all opcache.* settings, types, defaults, notes |
| production.md | Production tuning guide — recommended values, cache saturation, deployment gotchas |
| preloading.md | Preloading deep dive — when to use it, Symfony setup, performance expectations |
Common Mistakes
Memory settings in FPM pool files don't work. opcache.memory_consumption and opcache.interned_strings_buffer are INI_SYSTEM, but OPcache allocates shared memory once at PHP startup — before pool configuration is applied. Settings in www.conf are silently ignored. Always configure in php.ini.
file_cache survives FPM reloads. When opcache.file_cache is set, systemctl reload php-fpm only clears the SHM cache. The disk cache persists and PHP reloads stale opcodes from it on restart. Full invalidation requires: rm -rf /var/cache/php/opcache/* && systemctl reload php-fpm.
Preloading is incompatible with Octane, Roadrunner, FrankenPHP, Lambda. These runtimes manage PHP state differently; enabling opcache.preload on them causes conflicts or is silently ineffective.
Key Concepts
Cache saturation — OPcache has no eviction. When memory is full and wasted memory is below max_wasted_percentage, every new script compiles on every request as if OPcache didn't exist. Monitor oom_restarts and cache_full via opcache_get_status().
Validate timestamps off — Disables filesystem stat() calls per request (~1–3% gain). Requires deliberate invalidation on deploy: opcache_reset(), opcache_invalidate(), or FPM reload.
JIT — Benefits CPU-bound code most (math, string processing). Negligible gain for typical I/O-bound web apps. Use tracing mode; allocate jit_buffer_size from separate memory (not memory_consumption).
Preloading — Loads files once at FPM startup. Useful only for apps already below ~100ms response time. Incompatible with Octane, Roadrunner, FrankenPHP, Lambda.