• Tutorials
  • Understanding OPcache in PHP

    Ansichten162

    OPcache is a built-in PHP extension that dramatically improves performance by caching precompiled script bytecode in shared memory. It ships with PHP and is enabled by default in modern versions, making it one of the easiest and most impactful performance wins available to any PHP application.

    #The Problem OPcache Solves

    PHP is an interpreted language. On every request, the PHP engine goes through several steps to run a script:

    1. Lexing — the raw PHP source is tokenized.
    2. Parsing — tokens are turned into an Abstract Syntax Tree (AST).
    3. Compilation — the AST is compiled into opcodes (low-level instructions for the Zend Engine).
    4. Execution — the Zend Engine runs the opcodes.

    Without caching, steps 1–3 repeat on every single request, even though the source code hasn't changed. For an application with hundreds of files per request, this is a substantial and entirely redundant cost.

    OPcache eliminates that redundancy by storing the compiled opcodes in shared memory after the first compilation. Subsequent requests skip lexing, parsing, and compilation entirely, jumping straight to execution.

    #How It Works

    When a script is requested for the first time, OPcache compiles it as usual but then stores the resulting opcodes in a shared memory segment. On later requests for the same file, OPcache checks whether a valid cached version exists and, if so, reuses it.

    To decide whether the cache is still valid, OPcache can check the file's modification timestamp. If the file hasn't changed, the cached opcodes are served. This timestamp validation can be tuned or disabled entirely for maximum performance in production.

    #Enabling and Configuring OPcache

    OPcache is configured through php.ini. The extension is loaded with:

     1zend_extension=opcache
    

    A typical production configuration looks like this:

     1[opcache]
     2opcache.enable=1
     3opcache.enable_cli=0
     4opcache.memory_consumption=256
     5opcache.interned_strings_buffer=16
     6opcache.max_accelerated_files=20000
     7opcache.validate_timestamps=0
     8opcache.revalidate_freq=0
     9opcache.save_comments=1
    10opcache.fast_shutdown=1
    

    #Key Directives Explained

    opcache.enable — Turns OPcache on for web requests. Set to 1 in all environments.

    opcache.enable_cli — Enables OPcache for the command-line SAPI. Usually left off (0) since CLI scripts are short-lived, though it can help long-running CLI processes.

    opcache.memory_consumption — The amount of shared memory (in MB) reserved for the opcode cache. Too small and scripts get evicted; a good starting point for medium-to-large apps is 128–256 MB.

    opcache.interned_strings_buffer — Memory (in MB) for storing interned strings. PHP stores identical strings once and reuses references, saving memory across requests.

    opcache.max_accelerated_files — The maximum number of files OPcache will cache. Set this above the total number of PHP files in your application. OPcache rounds this up to the next prime number internally.

    opcache.validate_timestamps — When 1, OPcache checks file timestamps to detect changes. When 0, it never checks, giving the best performance but requiring a manual cache reset (or service restart) after every deploy.

    opcache.revalidate_freq — How often (in seconds) timestamps are checked when validation is enabled. A value of 0 means check on every request; higher values reduce filesystem stat calls.

    #Production vs. Development

    The right configuration depends heavily on the environment.

    In development, you want changes to take effect immediately:

     1opcache.validate_timestamps=1
     2opcache.revalidate_freq=0
    

    This makes OPcache re-check every file on each request, so edits are picked up instantly without sacrificing much speed.

    In production, you want maximum performance and predictable behavior:

     1opcache.validate_timestamps=0
    

    With timestamp validation off, OPcache never checks the filesystem, but you must clear the cache when deploying new code. Common approaches include restarting PHP-FPM, calling opcache_reset(), or using a deployment tool that handles this.

    #The JIT Compiler

    Starting with PHP 8.0, OPcache also houses the Just-In-Time (JIT) compiler. JIT goes a step further than opcode caching: it compiles opcodes into native machine code at runtime, which can be executed directly by the CPU.

    JIT is configured with two main directives:

     1opcache.jit_buffer_size=128M
     2opcache.jit=tracing
    

    The opcache.jit setting accepts a mode (tracing is the most common and generally most effective). JIT provides the largest gains for CPU-intensive, computation-heavy workloads — think mathematical processing, image manipulation, or long-running calculations. For typical I/O-bound web applications (database queries, file access), the benefit is usually modest, since the bottleneck isn't PHP execution speed.

    #Useful Runtime Functions

    OPcache exposes several functions for managing and inspecting the cache at runtime:

    • opcache_get_status() — Returns detailed information about cache usage, hit rates, memory consumption, and cached scripts.
    • opcache_get_configuration() — Returns the current configuration directives and their values.
    • opcache_reset() — Clears the entire cache, forcing recompilation of all scripts.
    • opcache_compile_file() — Compiles and caches a script without executing it, useful for warming the cache.
    • opcache_invalidate() — Invalidates a specific cached script, optionally forcing it regardless of timestamp.

    A simple status check might look like:

     1$status = opcache_get_status();
     2
     3printf(
     4    "Cache hits: %d, misses: %d, hit rate: %.2f%%\n",
     5    $status['opcache_statistics']['hits'],
     6    $status['opcache_statistics']['misses'],
     7    $status['opcache_statistics']['opcache_hit_rate']
     8);
    

    #Monitoring the Cache

    Keeping an eye on a few metrics tells you whether OPcache is configured well:

    • Hit rate — Should be very high (above 99%) in a stable production system. A low rate suggests scripts are being evicted, often due to insufficient memory.
    • Memory usage — If used memory is consistently near the limit, increase opcache.memory_consumption.
    • Cached keys vs. max — If the number of cached scripts approaches max_accelerated_files, raise that limit.
    • Restarts — Frequent OOM (out-of-memory) restarts indicate the cache is too small for the workload.

    Several open-source dashboards (such as the popular opcache-gui) visualize opcache_get_status() output for easier monitoring.

    #Common Pitfalls

    Forgetting to reset after deploys. With validate_timestamps=0, new code won't be served until the cache is cleared. Automate this in your deployment pipeline.

    Undersized memory. Setting memory_consumption too low causes constant eviction and restarts, which can be worse than having no cache benefit at all.

    Stripping comments unintentionally. Setting opcache.save_comments=0 saves memory but breaks any library that reads docblock annotations (many ORMs, dependency injection containers, and frameworks rely on them). Keep it at 1 unless you're certain nothing needs them.

    Expecting JIT to fix I/O-bound apps. JIT speeds up computation, not database or filesystem latency. Measure before assuming it will help your specific workload.

    #Summary

    OPcache is essential infrastructure for any production PHP deployment. By caching compiled opcodes in shared memory, it removes the repeated cost of parsing and compiling scripts on every request, typically delivering large performance improvements for almost no effort. Tune validate_timestamps to match your environment, allocate enough memory to avoid evictions, and consider JIT for compute-heavy workloads. With sensible configuration and basic monitoring, OPcache reliably keeps PHP applications fast.

    profile image of Petar Vasilev

    Petar Vasilev

    Petar is a web developer at Mitkov Systems GmbH. He is fascinated with the web. Works with Laravel and its ecosystem. Loves learning new stuff. Writes with the help of #ai.

    More posts from Petar Vasilev