Measuring Before Optimizing

Measure, change one thing, and measure again. A page you blame on slow PHP often spends most of its time waiting on one unindexed query (MySQL), which no OPcache setting can fix, so first time the phases of a slow request. The Server-Timing header carries named durations that browser developer tools draw on the network timeline, and hrtime() is a monotonic clock with nanosecond resolution:

timing.php: timing the phases of a requestPHP
<?php
$t0 = hrtime(true);
usleep(12_000);                                  // stands in for the database queries
$t1 = hrtime(true);
$html = str_repeat('<li>Deluxe Kettle</li>', 50_000);
$t2 = hrtime(true);
header(sprintf('Server-Timing: db;dur=%.1f, render;dur=%.1f',
    ($t1 - $t0) / 1e6, ($t2 - $t1) / 1e6));
echo strlen($html), " bytes\n";
Output
$ curl -si http://localhost/timing.php | grep -iE 'server-timing|bytes'
Server-Timing: db;dur=12.2, render;dur=0.8
1100000 bytes

When phases do not explain the time, a profiler records every call. Xdebug 16,266 's profiler (Profiling with Xdebug) is free and writes Cachegrind files. SPX 2,640 (github.com/NoiseByNorthwest/php-spx (https://github.com/NoiseByNorthwest/php-spx 2,640 ), GPL-3.0, PHP 5.4 to 8.5, built with phpize) adds a browser UI with flame graphs, enabled by spx.http_enabled=1 and a spx.http_key; its README calls it experimental and meant for non-production machines. Blackfire 41,699 is a commercial, subscription-priced profiler built for low overhead in staging and production. Profilers slow what they measure: find hot spots with them, and measure throughput with load tests (Load Testing).