Location: PHPKode > scripts > Script timer > script-timer/script_timer_nodoc.inc.php
<?php

class script_timer {

	var $dir;
	var $calc_precision = 10;
	var $output_precision = 4;
	var $output_encoding = 'utf-8';
	var $template_class = '/classes/phpbbtemplate.inc';
	var $template_path = '/templates/';
	var $template_file_timer = 'script_timing.tpl';
	var $template;
	var $start_next;
	var $timer_total = 0;
	var $scripttiming = array();
	var $timer_paused = false;
	var $timer_stopped = false;
	var $subtotals_added;
	var $lang_strings = array(
		'subtotal'	=>	'Subtotal of :', 		// used in end_timer()
		'end_timer'	=>	'End of script timing', // used in end_timer()
		'interim_marker'	=>	'Processing between setting of last manual marker and calling add_markers method' 							// used in add_markers()
	);


	function script_timer( $calc_precision = null, $auto_start = false ) {
		if( isset( $calc_precision ) && is_int( $calc_precision ) ) {
			$this->calc_precision = $calc_precision;
		}
		if( ini_get( 'precision' ) < $this->calc_precision ) {
			ini_set( 'precision', $this->calc_precision );
		}

		if( !extension_loaded( 'bcmath' ) ) {
			trigger_error('Your system is compiled without the <strong><em>bcmath</em></strong> extension - all calculations will use float values which by definition are less precise and could lead to unexpected results', E_USER_WARNING );
		}

		$this->dir = dirname(__FILE__);

		if( $auto_start === true ) {
			$this->start_next = microtime();
		}
	}


	function start_timer() {
		$this->reset();
		$this->start_next = microtime();
	}


	function add_markers( $marker_array, $start_time = null, $add_marker_for_interim = true, $marker_name = null, $script_name = null ) {

		$time = microtime();

		if( $this->timer_stopped === true ) {
			trigger_error( 'You tried to add markers after stopping the script timer.<br />No markers were set.<br />To start a new timing sequence, destroy the previous timing first with reset()', E_USER_WARNING );
			return;
		}

		if( isset( $this->start_next ) ) {
			trigger_error( 'You tried to add markers through the add_markers() method after starting the script timer.<br />No markers were set.<br />To start a new timing sequence, destroy the previous timing with reset() before calling this method', E_USER_WARNING );
			return;
		}
		else {
			$this->reset();
			$this->start_next = ( !is_null( $start_time ) ) ? $start_time : $marker_array[0][0];
		}

		foreach( $marker_array as $marker ) {

			$start = $this->transform_microtime( $this->start_next );
			$end = $this->transform_microtime( $marker[0] );

			$elapsed = $this->bc_sub( $end, $start );
			$this->timer_total = $this->bc_add( $this->timer_total, $elapsed );

		 	$this->scripttiming[] = array(
		 		'microtime_end'		=>	$end,
	 			'microtime_elapsed'	=>	$elapsed,
			 	'microtime_start'	=>	$start,
		 		'marker_name'		=>	$marker[1],
			 	'script_name' 		=> 	( ( isset( $marker[2] ) ) ? $marker[2] : null )
			);

		 	$this->start_next = $marker[0];
		}

		if( $add_marker_for_interim === true ) {

			$start = $this->transform_microtime( $this->start_next );
			$end = $this->transform_microtime( $time );

			$elapsed = $this->bc_sub( $end, $start );
			$this->timer_total = $this->bc_add( $this->timer_total, $elapsed );

	 		$this->scripttiming[] = array(
	 			'microtime_end'		=>	$end,
 				'microtime_elapsed'	=>	$elapsed,
		 		'microtime_start'	=>	$start,
	 			'marker_name'		=>	( ( !is_null( $marker_name ) ) ? $marker_name : $this->lang_strings['interim_marker'] ),
		 		'script_name' 		=> 	( ( !is_null( $script_name ) ) ? $script_name : null )
			);

			$this->start_next = microtime();
		}
		else {
			$this->start_next = $this->bc_add( $marker[0], $this->bc_sub( $this->transform_microtime( microtime() ), $time ) );
		}

	}


	function set_marker( $marker_name, $script_name = null, $pause_timer = false ) {

		$time = microtime();

		if( $this->timer_stopped === true ) {
			trigger_error( 'You tried to set a marker after stopping the script timer. No marker was set.<br />To start a new timing sequence, use the start_timer() method - beware : this will destroy previously recorded results.', E_USER_WARNING );
			return;
		}

		if( $this->timer_paused === true ) {
			trigger_error( 'You tried to set a marker while the timer has been paused. No marker was set.<br />Unpause the timer using the unpause() method before setting a new marker.', E_USER_WARNING );
			return;
		}

		if( !isset( $this->start_next ) ) {
			$this->reset();
		}

		$start = ( !is_null( $this->start_next ) ? $this->transform_microtime( $this->start_next ) : $this->transform_microtime( $time ) );
		$end = $this->transform_microtime( $time );

		$elapsed = $this->bc_sub( $end, $start );
		$this->timer_total = $this->bc_add( $this->timer_total, $elapsed );

	 	$this->scripttiming[] = array(
	 		'microtime_end'		=>	$end,
	 		'microtime_elapsed'	=>	$elapsed,
		 	'microtime_start'	=>	$start,
		 	'marker_name'		=>	$marker_name,
		 	'script_name' 		=> 	( ( !is_null( $script_name ) ) ? $script_name : null )
		);

		if( $pause_timer === true ) {
			$this->timer_paused = true;
		}

		$this->start_next = microtime();
	}


	function unpause() {
		$this->timer_paused = false;
		$this->start_next = microtime();
	}


	function end_timer( $add_subtotals = false, $marker_name = null, $script_name = null ) {

		$time = microtime();

		if( $this->timer_stopped === true ) {
			trigger_error( 'The script timer was already ended - no action taken', E_USER_WARNING );
			return;
		}
		elseif( $this->timer_paused === false ) {

			// Set the end marker
			$start = ( !is_null( $this->start_next ) ? $this->transform_microtime( $this->start_next ) : $this->transform_microtime( $time ) );
			$end = $this->transform_microtime( $time );

			$elapsed = $this->bc_sub( $end, $start );
			$this->timer_total = $this->bc_add( $this->timer_total, $elapsed );

	 		$this->scripttiming[] = array(
	 			'microtime_end'		=>	$end,
	 			'microtime_elapsed'	=>	$elapsed,
		 		'microtime_start'	=>	$start,
		 		'marker_name'		=>	( !is_null( $marker_name ) ? $marker_name : $this->lang_strings['end_timer'] ),
		 		'script_name' 		=> 	( !is_null( $script_name ) ? $script_name : null )
			);
			unset( $start, $end, $elapsed, $time );
		}


		// Add extra measurements
		sort( $this->scripttiming, SORT_REGULAR );

		$overall_subtotal = 0;
		$script_start = '';
		$script_elapsed = '';
		$count = count( $this->scripttiming );

		for( $i = 0; $i < $count; $i++ ) {
			$array = $this->scripttiming[$i];

			// Calculate measurements and add the to the result array
			$perc_elapsed = $this->bc_perc( $array['microtime_elapsed'], $this->timer_total );
			$overall_subtotal = $this->bc_add( $overall_subtotal, $array['microtime_elapsed'] );
			$cum_perc = $this->bc_perc( $overall_subtotal, $this->timer_total );

			$this->scripttiming[$i]['perc_elapsed'] = $perc_elapsed;
			$this->scripttiming[$i]['subtotal'] = $overall_subtotal;
			$this->scripttiming[$i]['cum_perc'] = $cum_perc;

			// Add subtotal records if so requested
			if( $add_subtotals === true && !is_null( $array['script_name'] ) ) {

				if( $i === 0 || $array['script_name'] !== $this->scripttiming[($i-1)]['script_name'] ) {
					$script_start = $array['microtime_start'];
					$script_elapsed = $array['microtime_elapsed'];
				}
				elseif( $array['script_name'] === $this->scripttiming[($i-1)]['script_name'] ) {
					$script_elapsed = $this->bc_add( $script_elapsed, $array['microtime_elapsed'] );
				}

				if( ( $i + 1 ) === $count || $array['script_name'] !== $this->scripttiming[($i+1)]['script_name'] ) {

					$perc_elapsed = $this->bc_perc( $script_elapsed, $this->timer_total );

					array_splice( $this->scripttiming, ( $i+1 ), 0, 0);
					$this->scripttiming[$i+1] = array(
			 			'microtime_end'		=>	$array['microtime_end'],
 						'microtime_elapsed'	=>	$script_elapsed,
				 		'microtime_start'	=>	$script_start,
	 					'marker_name'		=>	$this->lang_strings['subtotal'] . ' ' .  $array['script_name'],
	 					'script_name' 		=> 	null,
	 					'perc_elapsed'		=>	$perc_elapsed,
	 					'subtotal'			=>	$overall_subtotal,
	 					'cum_perc'			=>	$cum_perc
					);
					$script_start = '';
					$script_elapsed = '';

					$count = count( $this->scripttiming );
					$i++;
				}
			}
		}

		$this->timer_stopped = true;
		$this->subtotals_added = $add_subtotals;
	}


    function get_output( $display = false, $precision = null, $encoding = null, $add_subtotals = null, $marker_name = null, $script_name = null ) {

    	if( $this->timer_stopped !== true ) {
	    	$this->end_timer( $add_subtotals, $marker_name, $script_name );
    	}

    	$encoding = ( !is_null( $encoding ) ? $encoding : $this->output_encoding );
    	$precision = ( !is_null( $precision ) ? $precision : $this->output_precision );

    	if( !class_exists( 'Template') ) {
    		include( $this->dir . $this->template_class );
    	}
    	if( !is_object( $this->template ) ) {
    		$this->template = new Template( $this->dir . $this->template_path );
    	}

    	$this->template->set_filenames( array(
    			'script_timing'	=> $this->template_file_timer
    		)
    	);

		foreach( $this->scripttiming as $marker ) {

			$this->template->assign_block_vars('row', array(
				'SCRIPTNAME'	=>	htmlspecialchars( $marker['script_name'], ENT_QUOTES, $encoding ),
				'MARKERNAME'	=>	htmlspecialchars( $marker['marker_name'], ENT_QUOTES, $encoding ),
				'MARKER_TIME'	=>	htmlspecialchars( sprintf( '%01.' . $precision . 'f', $marker['microtime_elapsed'] ), ENT_QUOTES, $encoding ),
				'MARKER_PERC'	=>	htmlspecialchars( sprintf( '%01.2f', $marker['perc_elapsed'] ), ENT_QUOTES, $encoding ),
				'CUM_TIME'		=>	htmlspecialchars( sprintf( '%01.' . $precision . 'f', $marker['subtotal'] ), ENT_QUOTES, $encoding ),
				'CUM_PERC'		=>	htmlspecialchars( sprintf( '%01.2f', $marker['cum_perc'] ), ENT_QUOTES, $encoding )
				)
			);

			if( is_null( $marker['script_name'] ) ) {
				$this->template->assign_block_vars('row.marker_row', array() );
			}
			else {
				$this->template->assign_block_vars('row.marker_script_row', array() );
			}
		}


		if( $display === false ) {
			ob_start();
			$this->template->pparse('script_timing');
			$table = ob_get_contents();
			ob_end_clean();

			$this->template->destroy();

			return $table;
		}
		else {
			$return = $this->template->pparse('script_timing');

			$this->template->destroy();

			return $return ;
		}
	}


	function reset() {
		$this->start_next = null;
		$this->timer_total = 0;
		$this->scripttiming = array();
		$this->timer_paused = false;
		$this->timer_stopped = false;
		$this->subtotals_added = null;
	}


	function transform_microtime( $microtime ) {
		return substr( $microtime, 11 ) . substr( $microtime, 1, 9 );
	}

	function bc_sub( $high, $low ) {
		if( extension_loaded( 'bcmath' ) ) {
			return bcsub( $high, $low, $this->calc_precision );
		}
		else {
			return ( $high - $low );
		}
	}

	function bc_add( $str1, $str2 ) {
		if( extension_loaded( 'bcmath' ) ) {
			return bcadd( $str1, $str2, $this->calc_precision );
		}
		else {
			return ( $str1 + $str2 );
		}
	}

	function bc_perc( $part, $total ) {
		if( extension_loaded( 'bcmath' ) ) {
			return bcdiv( bcmul( $part, '100', $this->calc_precision ), $total, $this->calc_precision );
		}
		else {
			return ( ( $part * 100 ) / $total );
		}
	}

} // END of class

?>
Return current item: Script timer