Benchmark <?PHP

/*
|----------------------------------------------------------------------------------------------------------------------------------
| Benchmark class
|----------------------------------------------------------------------------------------------------------------------------------
|
| Measures the durations of events in your code or SQL
|
| I have found the best way of using it is to set a config variable, eg:
|
| $config['benchmark']=true;    
|
| somewhere early in your code, then comment/uncomment as required.
|
| I set up queries by putting $this->benchmarker=&benchmark::getInstance(); at the start of my db class, then putting 
|
|                $benchCode=$this->benchmarker->start(); 
|
| at the start of every sql function and 
|
|                $this->benchmarker->stop($benchCode,$str_sql);
|
| at the end. $str_sql is the SQL string that has just been executed. 
| This builds up an array of every bit of sql that is executed, along with execution times
|
|
*/
class benchmark{

    var 
$marker = array();                    // marked points to start counting from
    
var $elapsedTimes = array();        // the times between the marked points above being started and stopped
    
var $sql = array();                        // a numeric array of SQL queries - if you can insert start/stop functions into your db


/*
|----------------------------------------------------------------------------------------------------------------------------------
| instantiate : benchmark
|----------------------------------------------------------------------------------------------------------------------------------
|
| starts a page marker by default - this is stopped in the displayBenchmark() function
|
*/
    
function benchmark(){
        
$this->start("pageStart");        // load a page start by default
    
}

    
/*
|----------------------------------------------------------------------------------------------------------------------------------
| getInstance
|----------------------------------------------------------------------------------------------------------------------------------
|
| instantiate/load the singleton, 
|
*/    
    
function &getInstance(){
        
        static 
$instance
        if (!
$instance) { 
            
$instance = new benchmark(); 
        } 
        return 
$instance
    }


/*
|----------------------------------------------------------------------------------------------------------------------------------
| start
|----------------------------------------------------------------------------------------------------------------------------------
|
| sets a named marker.  eg: start('main loop');
| if you call stop('main loop') at some later point it will store the time between start and stop in an array
| If you call elapsed_time('main loop') at some later point, it will return the time elapsed
|
*/
    
function start($name=''){

        if (!
$name$name=md5(microtime());

        
$this->marker[$name] = microtime();
        
        return 
$name;
    }
      

/*
|----------------------------------------------------------------------------------------------------------------------------------
| stop
|----------------------------------------------------------------------------------------------------------------------------------
|
| sets a named marker.  eg: open('start loop');
| If you call elapsed_time('start loop') at some later point, it will return the time elapsed.
|
| including sql allows an external db class to build up an array of sql execution times
|
*/
    
function stop($name,$str_sql=''){

        if (
$str_sql) {

            
$this->sql[]=array("time"=>$this->elapsed_time($name),"qry"=>$str_sql);

        }else{

            
$this->elapsedTimes[$name] = $this->elapsed_time($name);
        }
    }
      

/*
|----------------------------------------------------------------------------------------------------------------------------------
| elapsed_time
|----------------------------------------------------------------------------------------------------------------------------------
|
| Calculates the time difference between two microtimes points.
| if there is no second point set, it calculates the time between the present, and the start of the first point

|
*/
    
function elapsed_time($point1 ''$point2 ''$decimals 4){

        
        if ( ! isset(
$this->marker[$point1]))    return '';
        
        if ( ! isset(
$this->marker[$point2]))    $this->marker[$point2] = microtime();
            
        list(
$sm$ss) = explode(' '$this->marker[$point1]);
        list(
$em$es) = explode(' '$this->marker[$point2]);

        return 
number_format(($em $es) - ($sm $ss), $decimals);
    }



/*
|----------------------------------------------------------------------------------------------------------------------------------
| displayBenchmark
|----------------------------------------------------------------------------------------------------------------------------------
|
| A rough and ready function that closes the the pageStart marker which was loaded when the class instantiated... 
| and displays the elapsed time of each marked event - including any database queries.
|
| Mixing HTML and PHP is something I never do - except here.
|
*/
    
function displayBenchmark(){

        
        
$str='<div style="width:500px;text-align:left;margin-left:50px;">';
        
        
$str.="<h3>Page loaded in :: ".$this->elapsed_time("pageStart")." seconds</h3>";

        if (
count($this->elapsedTimes)) {

            
$str.='<h3>Marked events</h3>';
            
$n=1;

            foreach(
$this->elapsedTimes as $name=>$time){
                
$str.="<p><b>".($n++)." :: ".$time." seconds</b> ::".$name."</p>";
            }
        }


        if (
count($this->sql)) {

            
$str.='<h3>SQL</h3>';
            
$n=1;

            foreach(
$this->sql as $qry){
                
$str.="<p><b>".($n++)." :: ".$qry['time']." seconds</b> ::".wordwrap($qry['qry'],100,"<br>",1)."</p>";
            }
        }
        
        
$str.="</div>";    

        return 
$str;
    }

// benchmark class endeth.
?>