Simple PHP performance profiling

One day you found that the page takes almost one minute to load. And it not happened before. You don't know which part of your program get a performance bottleneck. But some complex sql queries looks suspicious.

You want to know how much time elapsed for each of these queries.

Here is a handy facility can helps

 
function microtime_todate($micro_date) {
    $date = date("Y-m-d H:i:s",$micro_date);
    return $date;
}
 
if(IsAdmin()) {
  echo "<table border=1><tr><td>time</td><td>name</td><td>so far</td><td>delta</td><td>per cent</td></tr>";
  reset($TIMER);
  $start=$prev=current($TIMER);
  $total=end($TIMER)-$start;
  foreach($TIMER as $name => $value) {
    $sofar=round($value-$start,3);
    $delta=round($value-$prev,3);
    $percent=round($delta/$total*100);
    echo "<tr><td>".microtime_todate($value)."</td><td>$name</td><td>$sofar</td><td>$delta</td><td>$percent</td></tr>";
    $prev=$value;
  }
  echo "</table><br/>";
}
 

Put this on the first and last of you script to see the time used to load the whole page.

 
$TIMER['START'] = microtime(TRUE);
$TIMER['END'] = microtime(TRUE);
 

Or add this snippet to your function

 
    public function YouFunction() {
         global $TIMER;
        $TIMER['START command YouFunction. microtime()] = microtime(TRUE);
         //... time consuming work herer
        $TIMER['END command YouFunction'. microtime()] = microtime(TRUE);
        return count($r);
    }
 

The output will be something looks like this, its easy to identify where is the bottleneck.

php performance profiling

Encapsulate it in a class

The global variable is not a optimal way of implementation. It feels better to put it in a class.

 
function microtime_todate($micro_date) {
    $date = date("Y-m-d H:i:s",$micro_date);
    return $date;
}
 
class SimplePerf{
    private $TIMER;
 
    public function perf_stub($name) {
        $this->TIMER[$name] = microtime(TRUE);
    }
 
    public function perf_dump() {
        if(IsAdmin()) {
            echo "<table border=1><tr><td>time</td><td>name</td><td>so far</td><td>delta</td><td>per cent</td></tr>";
            reset($this->TIMER);
            $start=$prev=current($this->TIMER);
            $total=end($this->TIMER)-$start;
            foreach($this->TIMER as $name => $value) {
                $sofar=round($value-$start,3);
                $delta=round($value-$prev,3);
                $percent=round($delta/$total*100);
                echo "<tr><td>".microtime_todate($value)."</td><td>$name</td><td>$sofar</td><td>$delta</td><td>$percent</td></tr>";
                $prev=$value;
            }
            echo "</table><br/>";
        }
    }
}
 
function perf(){
    static $perf = NULL;
    if( $perf == NULL) {
        $perf = new SimplePerf();
    } 
    return $perf;       
}
 

Here we are using a singleton, not the best but better than global variable. How to use

 
perf()->perf_stub("START");
perf()->perf_stub("END");
perf()->perf_dump();
 

Include those code in the global space, a small class like this doesn't even need an independent class file. Keep it in your personal toolbox, it will gonna helps a lot.