OPcache Tuning
debt(d5/e1/b3/t7)
Closest to 'specialist tool catches' (d5), since opcache-gui, phpinfo, and blackfire from detection_hints can reveal hit rate and config issues, but only if you go look — it's silent otherwise.
Closest to 'one-line patch' (e1), the quick_fix is just adjusting a handful of php.ini directives (validate_timestamps=0, memory_consumption=256, etc.) — config-only change.
Closest to 'localised tax' (b3), applies_to web context only and lives in php.ini; once tuned it doesn't shape application code, though deployment workflow must include cache reset.
Closest to 'serious trap' (t7), the misconception that OPcache is enabled-and-done is widespread, and the validate_timestamps=0 setting contradicts dev-mode expectations — deploys silently serve stale bytecode unless explicitly invalidated.
Also Known As
TL;DR
Explanation
PHP compiles scripts to opcodes on every request by default. OPcache caches these in shared memory, making subsequent requests skip compilation entirely — typically 2-5× faster with zero code changes. Key settings: opcache.memory_consumption (size of shared memory, 128-256MB for large apps), opcache.max_accelerated_files (number of files to cache — must exceed your total PHP file count), opcache.validate_timestamps (set to 0 in production for maximum performance, invalidate manually on deploy), opcache.preload (PHP 7.4+ — load frequently used classes into memory at startup).
Diagram
flowchart TD
subgraph Without OPcache
REQ1[Request 1] --> PARSE1[Parse PHP files]
PARSE1 --> COMPILE1[Compile to opcodes]
COMPILE1 --> EXEC1[Execute]
REQ2[Request 2] --> PARSE2[Parse again!]
PARSE2 --> COMPILE2[Compile again!]
end
subgraph With OPcache
REQ3[Request 1] --> PARSE3[Parse and compile]
PARSE3 --> CACHE[(Shared memory cache)]
REQ4[Request 2] --> CACHE
CACHE --> EXEC2[Execute - skip parse+compile]
end
style PARSE2 fill:#f85149,color:#fff
style COMPILE2 fill:#f85149,color:#fff
style CACHE fill:#238636,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- opcache.validate_timestamps=1 in production — checks file mtime on every request, adding syscall overhead.
- opcache.max_accelerated_files too low — files not in cache fall back to recompilation.
- opcache.memory_consumption too small — cache evictions cause thrashing.
- Not invalidating the cache after deployment — stale bytecode serves old code when validate_timestamps=0.
Code Examples
; Default/untuned OPcache — suboptimal for production:
opcache.enable=1
opcache.memory_consumption=64 ; Too small for large apps
opcache.max_accelerated_files=2000 ; Too few for Composer apps
opcache.validate_timestamps=1 ; File stat on every request
; No preload configured
; Production-tuned OPcache:
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256 ; 256MB — covers large apps
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000 ; More than your total PHP files
opcache.validate_timestamps=0 ; No stat check — invalidate on deploy
opcache.save_comments=1 ; Required for annotations/attributes
opcache.preload=/var/www/app/preload.php ; PHP 7.4+
; Deploy script:
; php -r "opcache_reset();" -- or reload PHP-FPM