Enabling PHP 8 JIT for CPU-Intensive Workloads: Configuration, Benchmarks, and Pitfalls
PHP 8's JIT compiler can speed up CPU-bound code but does little for I/O-bound web apps. Learn how to enable it safely, verify it is active, benchmark the real impact, and roll back if needed.
24 Aug 2026, 07:13 UTC

When JIT is worth the trouble
PHP 8.0 added a Just-In-Time (JIT) compiler to OPcache. It watches which code paths execute most often and compiles those "hot" traces into native machine code, skipping the interpreter for repeated work. The catch: most web applications are I/O-bound — they spend their time waiting on databases, HTTP calls, and filesystem reads — so JIT often produces little or no measurable gain there. The useful takeaway: enable JIT only after confirming your bottleneck is CPU-bound PHP code (math, parsing, image or data processing, algorithmic loops), and verify the gain with a benchmark rather than assuming it.
Prerequisites
- PHP 8.0 or newer. Confirm with
php -v. - OPcache available and enabled. JIT is part of OPcache, not a separate extension.
- Access to the PHP configuration for the SAPI you care about. Note that CLI and FPM often use different
php.inifiles — checkphp --inifor CLI andphpinfo()output for FPM. - Permission to restart PHP-FPM (or your web server) after configuration changes.
- A staging environment. Do not enable JIT for the first time in production.
Configuration procedure
Run these steps on the server (or container) whose configuration you control, as a user with write access to the PHP ini files.
- Confirm OPcache is loaded:
php -m | grep -i opcache. If nothing prints, enable the OPcache extension first (zend_extension=opcachein your ini). - Edit the
php.inifor the relevant SAPI and set:opcache.enable=1 opcache.enable_cli=1 ; only if you want JIT for CLI scripts opcache.jit=tracing opcache.jit_buffer_size=100Mopcache.jit=tracingselects the tracing JIT, the default and recommended mode in PHP 8.0+. You may also see numeric forms such asopcache.jit=1205in older guides; these are bitmasks controlling the same behavior, and the named form is easier to read.opcache.jit_buffer_sizereserves shared memory for compiled machine code; without it, JIT stays off. 100M is a common starting point, not a requirement. - Restart PHP-FPM:
sudo systemctl restart php-fpm(service name varies by distribution, e.g.php8.2-fpm). For CLI, no restart is needed — each invocation reads the ini fresh.
Verify JIT is actually active
Do not trust the ini edit alone. Check the runtime state:
php -i | grep -i jitYou should see opcache.jit => tracing and your buffer size. For a live FPM process, run a temporary script on the same pool:
<?php
$status = opcache_get_status(false);
var_dump($status['jit'] ?? 'no jit info');The jit section reports whether JIT is enabled and how much of the buffer is used. Remove this script after checking — it exposes internals. If buffer_size is reported as 0, your buffer setting did not take effect (wrong ini file is the usual cause).
Benchmark before and after
JIT's value is workload-specific, so measure your own code. A minimal approach:
- For a CPU-bound script, time it directly:
time php bench.phpwith JIT on and off (toggle viaphp -d opcache.jit=disable bench.phpfor a quick comparison without editing ini). - For a web endpoint, use a load tool such as
wrkor Apache Bench (ab -n 1000 -c 20 https://staging.example.com/heavy-endpoint) against staging, and compare latency and throughput across both configurations.
If the difference is within noise (a few percent), the honest answer is that JIT does not help this workload, and you should weigh leaving it off.
Known limitations and risks
- Memory: the JIT buffer is allocated on top of the normal OPcache shared memory. If the buffer fills, compilation of new traces stops and those paths fall back to the interpreter — check buffer usage via
opcache_get_status()under realistic load. - Dynamic code: applications that lean heavily on
eval()or runtime-generated code may behave unpredictably or gain nothing, since generated code does not form stable hot traces. - Tooling conflicts: some debuggers and profilers that hook the engine are incompatible with JIT. Disable JIT in development environments where you use such tools.
- Startup cost: short-lived scripts with large codebases but small executed paths can pay compilation overhead without benefit.
Rollback
Enabling JIT changes runtime behavior, so keep a rollback path: set opcache.jit=disable in the same ini file and restart PHP-FPM. OPcache itself continues working normally; only the compilation layer is turned off. Because the change is a single ini directive plus a service restart, reverting takes under a minute.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.