time_start = ""; $this->numStarts = 0; } public function start(){ if($this->numStarts == 0){ $this->time_start = microtime(true); } $this->numStarts++; } public function stop(){ $this->numStarts--; return microtime(true); } public function isStopped(){return ($this->numStarts == 0);} public function getStartTime(){return $this->time_start;} } } //// // Marks the beginning of a chunk of code for the profiler to analyze. //// function profiler_beginSection($sectionName){ if(RUN_PROFILER){ GLOBAL $profiler_timers; if(isset($profiler_timers[$sectionName])){ $profiler_timers[$sectionName]->start(); // doesn't change the time, just allows this nested call to be ignored. } else { $timer = new Profiler_Timer(); $timer->start(); $profiler_timers[$sectionName] = $timer; } } } // end profiler_beginSection() //// // Marks the end of a chunk of code for the profiler to analyze. //// function profiler_endSection($sectionName){ if(RUN_PROFILER){ GLOBAL $profiler_timers,$profiler_stats; if(isset($profiler_timers[$sectionName])){ $timer = $profiler_timers[$sectionName]; $time_end = $timer->stop(); if($timer->isStopped()){ $time_start = $timer->getStartTime(); if(! isset($profiler_stats[$sectionName])){ $profiler_stats[$sectionName] = array(0,0); } $profiler_stats[$sectionName][PROFILER_STATS_TOTAL_TIME] += ($time_end - $time_start); $profiler_stats[$sectionName][PROFILER_STATS_NUM_RUNS]++; unset($profiler_timers[$sectionName]); // done with this timer, remove it from the group of active timers } } else { print "WARNING: Profiler: Trying to end a section which does not have a timer running: \"$sectionName\"."; if(isset($profiler_stats[$sectionName])){ print " There are stats for this section-name, so the section may have already been ended."; } print "\n"; } } } // end profiler_endSection() //// // Displays the results of the profiler. // If there are any open timers, this just closes them. // // TODO: Either chose a logical sorting method (as-used, alphabetical, by total||average time, by number of calls) or allow // a sorting type to be passed in or configured. Another option would be to use jQuery sorttables. // // WARNING: After this function is called, if there were any timers open it will no longer be accurate to call this function // again. A good rule to follow is to call this function only once per page-load unless you understand what this means. //// function profiler_printResults(){ if(RUN_PROFILER){ // Close all open timers. GLOBAL $profiler_timers,$profiler_stats,$profiler_startedAt; $hangingTimers = array(); print "
\n";
		while(count($profiler_timers) > 0){
			foreach($profiler_timers as $sectionName=>$timer){
				print "WARNING: Profiler: Closing hanging timer... \"$sectionName\".\n";
				$hangingTimers[] = $sectionName;
				profiler_endSection($sectionName);
			}
		}

		// Go through the stats and display the table.
		$totalTime = $totalRuns = 0;
		$precision = 5; // chosen arbitrarily... number of decimal points to display in the results
		print "\n";
		print "\n";
		foreach($profiler_stats as $sectionName => $statsArray){
			$total = $statsArray[PROFILER_STATS_TOTAL_TIME];
			$numRuns = $statsArray[PROFILER_STATS_NUM_RUNS];
			$totalTime += $total;
			$totalRuns += $numRuns;
			print "";
			print "";
			print "";
			print "";
			print "";
			print "\n";
		}
		print "";
		print "";
		print "";
		print "";
		print "\n";
		print "
Section Name total(sec) calls ave(sec)
$sectionName".number_format($total, $precision, '.', '')."$numRuns".number_format(($total / $numRuns), $precision, '.', '')."
Totals".number_format($totalTime, $precision, '.', '')."$totalRuns".number_format(($totalTime / $totalRuns), $precision, '.', '')."
\n"; print "Total runtime (including code that wasn't profiled): "; print number_format(microtime(true) - $profiler_startedAt, $precision, '.', ''); print "
\n"; // Reopen timers that were hanging so that they can be closed without throwing warnings later. // WARNING: These timers won't be accurate after this point (since part of the run was recorded // already as being a whole run, and the remainder of this run will be recorded as another separate run). foreach($hangingTimers as $sectionToReopen){ profiler_beginSection($sectionToReopen); } } else { print "WARNING: Called ".__FUNCTION__ ." but profiling is disabled.\n"; } } // end profiler_printResults() ?>