skip to content

OPcache & JIT

OPcache keeps compiled opcodes in shared memory, preloading loads classes at startup, and the JIT compiles hot code to machine code. Interviewers ask what each one buys a web app.

part ofPHPoverview, primer and where to startread it →
on this pageshow

explore

questions

6

In PHP, what does OPcache do for a web application, and what does it not cache?

level: juniorimportance: must knowfreq 70%

answer

  1. skip the compile step
  2. opcodes in shared memory
  3. shared by one server's worker processes
  4. not data, not output
  5. always built in since 8.5

basics

~20 s

OPcache stores each script's compiled opcodes in shared memory, so later requests skip reading and compiling the PHP source and run the cached opcodes directly. It caches code only: not query results, not rendered pages, not application data.

solid answer

~40 s

Without an opcode cache, every request reads each PHP file, tokenises and parses it, and compiles it to **opcodes** before running them. OPcache keeps those compiled scripts in **shared memory**, so every worker process of the same server — the PHP-FPM workers under one master, say — reuses them and skips the compile step. It also applies optimisation passes and stores **interned strings** (class names, literals) once. What it does **not** do is cache data: query results, API responses and rendered HTML are the job of a user cache such as APCu or an external store. It is on by default for web SAPIs (`opcache.enable=1`) and off for the CLI (`opcache.enable_cli=0`), and since PHP 8.5 it is always compiled into the binary rather than loaded as a separate extension.

go deeper

for a junior

Say that OPcache stores compiled opcodes in shared memory so requests skip compiling, and that it does not cache data or output.

for a middle

Explain what is in the shared segment — scripts, interned strings, the key index — and why CLI processes do not see the web server's cache.

for a senior

Read opcache_get_status() hit rates and memory figures to judge whether the cache is warm, sized right, and not being reset too often.

for a principal

Position OPcache as the baseline every PHP deployment must have, and direct tuning effort at data caching and I/O where the real latency lives.

## The problem OPcache solves PHP source is not executed directly. Before a script runs, the engine reads the file, turns it into tokens, builds a syntax tree and compiles that tree into **opcodes** — the instruction format the Zend Engine executes. Without a cache, that work is repeated for every file on every request, because nothing in a normal web request survives to the next one. **OPcache** removes the repetition. The first time a script is compiled, OPcache stores the result in a **shared memory** segment. The next request that includes the same file finds it there and runs the cached opcodes, skipping the read, parse and compile steps. ## What is stored, and where - **Compiled scripts**: the opcodes of each file, together with its classes and functions, in a form that can be used without copying. - **Interned strings**: identical strings such as class names, method names and literals are stored once and shared, sized by `opcache.interned_strings_buffer`. - **Optimised code**: OPcache runs optimisation passes over the opcodes before storing them, controlled by `opcache.optimization_level`. - **An index**: a hash table of cached scripts, sized by `opcache.max_accelerated_files`. The memory is created when the server starts and shared by the processes that start from it — for PHP-FPM, the workers forked by one master. A separate `php` command run from a shell is a different process with its own cache, or none at all. ## What it does not cache | Thing | Cached by OPcache? | Where it belongs | |---|---|---| | compiled PHP code | yes | OPcache | | database query results | no | a user cache (APCu) or an external store | | rendered HTML or JSON | no | a page or HTTP cache | | session data | no | the session handler's storage | | values in PHP variables | no | nothing survives the request | This is the most common confusion in interviews: OPcache makes the **code** cheaper to start, not the **work** the code does. A page that spends 300 ms waiting on a slow query is still slow with OPcache enabled. ## Defaults and switches 1. `opcache.enable` defaults to `1`: web SAPIs use OPcache unless you turn it off. 2. `opcache.enable_cli` defaults to `0`: command-line scripts do not use it. Enabling it helps long CLI jobs only modestly, because a single process compiles each file once anyway. 3. `opcache.memory_consumption` (default `128`, in megabytes) sizes the shared segment. 4. `opcache.validate_timestamps` (default `1`) makes OPcache notice edited files; production servers often turn it off and reset the cache on deploy instead. ## What changed in PHP 8.5 Before PHP 8.5, OPcache was a separate Zend extension that had to be loaded with a `zend_extension=opcache` line, and some builds shipped without it. Since PHP 8.5 it is **always built into the PHP binary and always loaded**; the `opcache.enable` and `opcache.enable_cli` switches are still honoured, and a leftover `zend_extension=opcache.so` line now produces a warning. ## Checking that it works - `opcache_get_status()` returns `false` when OPcache is not running in the calling process (the CLI with `opcache.enable_cli=0`, for instance), or an array with memory usage, hit and miss counts and the hit rate. - A healthy production server shows a hit rate close to 100 % once it has warmed up; a low rate points at a cache that is too small or constantly reset. ## Where OPcache sits among PHP's caches Several caches share the word, and interviewers like to check that you keep them apart: - **OPcache** — compiled code, shared by the workers of one server. - **A user cache such as APCu** — values your code stores explicitly with its own keys and TTLs, also per server. - **The realpath cache** — resolved file paths, per process, so includes do not repeat filesystem lookups. - **External caches** — a separate server shared by many PHP hosts, for data that must be consistent across them. Only the first is automatic. The others hold data your application chooses to keep, and none of them replaces OPcache or is replaced by it. OPcache is also the home of PHP's **JIT** compiler and of **preloading**; both build on the same shared memory and are switched on separately.

  • Does OPcache speed up a page that is slow because of a database query?
    No. OPcache removes the cost of reading and compiling PHP files. Time spent waiting for the database, the network or the disk is unchanged. For that you cache the data itself, or fix the query.
  • Why does running `php -r 'var_dump(opcache_get_status());'` not show the web server's cache?
    The shared memory belongs to the server process tree, such as one PHP-FPM master and its workers. A CLI command is a separate process: with the default `opcache.enable_cli=0` it has no cache and the call returns `false`; with CLI enabled it sees only its own, fresh cache.

A restaurant kitchen that keeps prepped ingredients between orders: the chopping happens once, and every cook on the same shift reuses it. It does not store finished meals, so a dish that takes long to cook still takes long.

saying these in an interview costs you the question

  • OPcache caches database query results
  • OPcache stores rendered HTML pages
  • A CLI script can inspect the FPM pool's OPcache
  • OPcache is disabled by default for web requests
  • OPcache must be loaded with zend_extension in PHP 8.5
open as a page

In PHP, what do opcache.validate_timestamps and opcache.revalidate_freq control, and why do production servers often disable validation?

level: middleimportance: must knowfreq 50%

basics

~20 s

With opcache.validate_timestamps=1 (the default) OPcache checks a cached script's modification time at most every opcache.revalidate_freq seconds (default 2) and recompiles it if it changed. Production often sets 0: no file checks at all, so a deploy must reset OPcache.

open as a page

In PHP, how do you size opcache.memory_consumption and opcache.max_accelerated_files, and how do you tell that OPcache is full?

level: middleimportance: should knowfreq 30%

basics

~20 s

Set opcache.max_accelerated_files above the number of PHP files the app can load, vendor included, and opcache.memory_consumption (default 128 MB) with headroom over measured use. opcache_get_status() shows a full cache as cache_full, low free memory, or rising oom_restarts or hash_restarts.

open as a page

After a PHP deploy on servers with opcache.validate_timestamps=0, the site keeps serving the old code; why, and how should the deploy clear OPcache?

level: seniorimportance: should knowfreq 40%

basics

~20 s

With validation off, OPcache never rereads changed files, so old compiled scripts keep running. Clear the cache inside its owner: call opcache_reset() through the web server's PHP, or restart or reload PHP-FPM; a CLI opcache_reset() cannot reach it.

open as a page

In PHP 8.5, how do you turn on the JIT compiler, and which workloads actually get faster with it?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Set opcache.jit=tracing (the recommended mode) with OPcache enabled; since PHP 8.4 the default is opcache.jit=disable with a 64M opcache.jit_buffer_size. The JIT speeds up CPU-bound PHP such as numeric loops and parsers; typical web requests waiting on databases gain little.

open as a page

In PHP, what does opcache.preload do, and what do you give up when you preload an application's classes?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

opcache.preload runs a script once at server start; the classes, functions, interfaces and traits it loads stay in shared memory and exist in every request without autoloading. The price: changes need a server restart, and the memory is always held.

open as a page