PHP: Elapsed time and page performance

A recent project had me scouring a code base for the cause of a site's incredibly poor performance. The site was pulling data from all over the place, and the code was extremely modular, nested, and non-linear, so tracking down the actual "Herbie" in the process was a real challenge. One of the first things I did was put together some "stopwatch" code to test the length of time each section took to run, as well as to test the impact of various changes on overall page load times. Here's what I came up with to measure and output the information.

The key to the entire exercise is a native PHP function called "microtime". This function returns, in seconds and microseconds, the length of time from the Unix "Epoc" (1/1/70 Midnight) to the current instant. To use it like a stop watch, you simply get a time stamp before the item to be measured, and then compare it to another one afterwards.

On to the nuts and bolts.

To start off, you need to initialize the key variables in the global area of you page, preferably at the very top before any cycle-consuming activities occur:

$sStartTime = microtime();
$sLastTime = $sStartTime;

Next, paste in this function somewhere:

function getTimeLapse($sPrevTime){
    global $sLastTime;
    $sCurrTime = microtime();
    $aCurrTime = explode( " " , $sCurrTime);
    $iCurrTime = $aCurrTime[1] + $aCurrTime[0];
    $aPrevTime = explode( " " , $sPrevTime);
    $iPrevTime = $aPrevTime[1] + $aPrevTime[0];
    $iTimeDiff = $iCurrTime - $iPrevTime;
    $iTimeDiff = round($iTimeDiff,5);
    $sLastTime = $sCurrTime;
    return $iTimeDiff;

All that's happening here is that I am taking an earlier time stamp passed to me, either the first one or the most recently made one, and comparing it against a new "current" stamp. The only "tricky" part is exploding the seconds and microseconds out of the microtime return. Do a little math, re-set the value of $sLastTime, and return the difference, in seconds.

To use the function, first make sure the passed time stamp is in scope. If you are in a function or otherwise unable to access global variables, declare the timestamp you need.

global $sLastTime;
global $sStartTime;

If intervening code you are not currently focused on has burned some cycles, you can add this right before the area you want to time in order to re-set the clock:

... or even just:
$sLastTime = microtime();

Otherwise, the time you are returned will be for the entire period since your previous invocation.

At the end of the area to be measured, add something like this:

echo "<p>This function ran in " .getTimeLapse($sLastTime). " seconds.</p>" ;
echo "<p>This page loaded in " .getTimeLapse($sStartTime). " seconds.</p>" ;

As you can see here, $sStartTime will always be the first timestamp, and is best suited to measure the load time for the entire page. For smaller blocks, you'll probably want to use $sLastTime.

Note that you can time the performance of wrapper blocks by just naming your own variable at the beginning.

$sBlockTime = microtime(); // <-- New variable to mark block start
$sLastTime = microtime();
 <!-- some code -->
echo "<p>This function ran in " .getTimeLapse($sLastTime). " seconds.</p>" ;
$sLastTime = microtime();
 <!-- some more code -->
echo "<p>This function ran in " .getTimeLapse($sLastTime). " seconds.</p>" ;
echo "<p>This block ran in " .getTimeLapse($sBlockTim). " seconds.</p>" ;

Make sure that any new variables you name are in scope.

And that's it. Hope it saves you a little time.