PHP StopWatch for Performance Measurement and Profiling

The stop watch will measure the time a given piece of code is executed. It will also make it possible to add as many stops as we need to compare times for different parts. Stops can be labeled.

The Solution

/**
 * StopWatch class.
 *
 * @author Ivan Georgiev
 */
class ig_StopWatch {
	var $timeInit;
	var $timeStart;
	var $timeStop = array();
	var $stopLabels = array();
 
	function ig_StopWatch() {
		$this->timeInit = $this->getMicrotime();
	}
 
	function start() {
		$this->timeStart = $this->getMicrotime();
	}
 
	function stop($label = null) {
		$this->timeStop[] = $this->getMicrotime();
		$this->stopLabels[] = $label;
	}
 
	function toString() {
		$start = $this->getStartMs();
		$string = "Total time: " . ($this->getMicrotime() - $start) . "\n";
		$lastTime = $start;
		for ($i=0; $i<count($this->timeStop); $i++) {
			$thisTime = $this->timeStop[$i];
			$thisLabel = $this->stopLabels[$i];
			$elTime = $thisTime - $lastTime;
			$string .= "  $i";
			if (! is_null($thisLabel)) $string .= " ($thisLabel)";
			$string .= ": $elTime\n";
			$lastTime = $thisTime;
		}
		return $string;
	}
 
	function printResult() {
		print $this->toString();
	}
 
	/**
	 * @access private
	 */
	function getStartMs() {
		return (isset($this->timeStart) ) ? $this->timeStart : $this->timeInit;
	}
 
	/**
	 * @access private
	 */
	function getMicrotime(){
		list($usec, $sec) = explode(" ",microtime());
		return ((float)$usec + (float)$sec);
	}
}

Example:

$watch = new ig_GlobalStopWatch();
$watch->start();
load_customers();
$watch->stop("Load Customers");
calculate_balance();
$watch->stop("Calculate Balance");
apply_pending_transactions();
$watch->stop("Apply Transactions");
$watch->printResult();

The result from above might look like the following:

Total time: 0.15867686271667
  0 (Load Customers): 0.052696943283081
  1 (Calculate Balance): 0.052886962890625
  2 (Apply Transactions): 0.05298900604248

Static Wrapper

Most of the times we would like to have a global StopWatch and we do not care of creating instances of this watch. To address this case, we created a GlobalStopWatch class which provides only static methods for accessing singleton StopWatch instance.

/**
 * Static wrapper to a singleton StopWatch instance.
 *
 * @author Ivan Georgiev
 */
class ig_GlobalStopWatch {
 
	function Start() {
		$watch =& ig_GlobalStopWatch::StopWatchInstance();
		$watch->start();
	}
 
	function Stop($label = null) {
		$watch =& ig_GlobalStopWatch::StopWatchInstance();
		$watch->stop($label);
	}
 
	function ToString() {
		$watch =& ig_GlobalStopWatch::StopWatchInstance();
		return $watch->toString();
	}
 
	function PrintResult() {
		$watch =& ig_GlobalStopWatch::StopWatchInstance();
		$watch->printResult();
	}
 
	/**
	 * @return ig_StopWatch
	 * @access private
	 */
	function & StopWatchInstance() {
		static $instance = array();
		if (!isset($instance[0])) {
			$instance[0] =& new ig_StopWatch();
		}
		return $instance[0];
	}
}

Example:

ig_GlobalStopWatch::Start();
load_customers();
ig_GlobalStopWatch::Stop("Load Customers");
calculate_balance();
ig_GlobalStopWatch::Stop("Calculate Balance");
apply_pending_transactions();
ig_GlobalStopWatch::Stop("Apply Transactions");
ig_GlobalStopWatch::PrintResult();

The result from above might look like the following:

Total time: 0.15867686271667
  0 (Load Customers): 0.052696943283081
  1 (Calculate Balance): 0.052886962890625
  2 (Apply Transactions): 0.05298900604248
 
php/howtos/codeprofile.txt · Last modified: 2009/10/31 23:39 (external edit)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki