The JIT

The JIT Compiler and When It Helps

The JIT (PHP 8.0, rebuilt on the IR framework in 8.4) compiles hot opcodes to machine code. tracing mode, the one the manual recommends, compiles hot paths through loops and functions; function mode compiles whole functions. Since 8.4, opcache.jit defaults to disable and opcache.jit_buffer_size to 64M (before: tracing and 0, which also meant off), so one line turns it on. A CPU-bound loop:

mandel.php: pure arithmetic in tight loops, the JIT's best casePHP
<?php
function mandel(int $size): int                  // points of a grid inside the Mandelbrot set
{
    for ($inside = 0, $y = 0; $y < $size; $y++) {
        for ($x = 0; $x < $size; $x++) {
            [$cr, $ci, $zr, $zi] = [3.0 * $x / $size - 2.0, 2.0 * $y / $size - 1.0, 0.0, 0.0];
            for ($i = 0; $i < 100 && $zr * $zr + $zi * $zi < 4.0; $i++) {
                [$zr, $zi] = [$zr * $zr - $zi * $zi + $cr, 2.0 * $zr * $zi + $ci];
            }
            $inside += (int) ($i === 100);
        }
    }
    return $inside;
}
$start = hrtime(true);
$n = mandel(1200);
printf("%-8s %d points  %.3f s\n", ini_get('opcache.jit'), $n, (hrtime(true) - $start) / 1e9);
Output
$ for m in disable function tracing; do
>   php -d opcache.enable_cli=1 -d opcache.jit=$m mandel.php; done
disable  371477 points  3.432 s
function 371477 points  1.832 s
tracing  371477 points  1.340 s

On this WSL2 6 machine tracing ran the loop 1.9 to 2.6 times faster across four runs. On the Laravel 2,157 page, two sessions each, it gave 1,463 and 1,508 requests per second against 1,404 and 1,431 without: 4 to 5%, which is typical: web requests spend their time in hash lookups, string building and waiting on MySQL 524 , which are already C code or I/O. Use the JIT for image work, parsers or math, and measure your own pages before keeping it anywhere else.