Timing a function in a loop measures the loop, the opcache state, the CPU frequency scaling and occasionally the garbage collector — and rarely the function.
// what this actually measures is unclear
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) { $x = strlen('abc'); }
echo microtime(true) - $start;
// what is missing:
// a warm-up run (opcache, CPU boost state)
// several rounds (variance is large and not reported)
// a baseline (the empty loop costs something)
// the compiler not optimising the call away entirely
The empty-loop baseline is the one people forget and it is frequently most of the measurement. Variance across runs on a laptop is routinely twenty percent, so a single number without a spread is not a result. For anything that matters, a proper harness such as PHPBench handles the warm-up, the rounds and the statistics — and the real answer is usually to profile a real request instead.