Application Profiling | > Module written by Brandon Farber | > Date started: Monday 28th February 2005 16:46 | | > Module Version Number: 1.0.0 +-------------------------------------------------------------------------- */ /** * IPS Kernel Pages: Application Profiling Layer [PHP5] * * @package IPS_KERNEL * @subpackage ApplicationProfiling * @author Brandon Farber * @copyright Invision Power Services, Inc. * @version 1.0 */ /** * Gateway for application profiling * * $a = new class_profiling(); * $a->output_results( true, false ); */ //----------------------------------------- // Define KERNEL_PATH if not // defined - i.e. installation //----------------------------------------- if ( ! defined('KERNEL_PATH') ) { if( defined('INS_KERNEL_PATH') ) { define( 'KERNEL_PATH', INS_KERNEL_PATH ); } else { define( 'KERNEL_PATH', str_replace( "//", "/", str_replace( "\\", "/", dirname( __FILE__ ) ) ) . "/" ); } } //----------------------------------------- // Define ROOT_PATH if not //----------------------------------------- if ( ! defined('ROOT_PATH') ) { $path = str_replace( "//", "/", str_replace( "\\", "/", dirname( __FILE__ ) ) ); $path_bits = explode( "/", $path ); array_pop( $path_bits ); define( 'ROOT_PATH', implode( "/", $path_bits ) . "/" ); } class class_profiling { var $start_time = array(); var $end_time = array(); var $running_time = array(); var $start_memory = array(); var $end_memory = array(); var $descriptions = array(); var $timer_stack = array(); var $internal_count = array(); var $stack_trace = null; var $cur_timer = null; var $init_time = 0; var $init_memory = 0; var $total_memory = 0; var $peak_memory = 0; function __construct( $start_apd = false ) { $this->start_time = array(); $this->end_time = array(); $this->running_time = array(); $this->start_memory = array(); $this->end_memory = array(); $this->descriptions = array(); $this->timer_stack = array(); $this->internal_count = array(); $this->stack_trace = "Profiling Class Initialized\n"; $this->cur_timer = null; $this->init_time = $this->get_micro_seconds(); $this->init_memory = $this->get_current_memory(); $this->total_memory = $this->init_memory; $this->peak_memory = $this->init_memory; if( $start_apd == true && function_exists( 'apd_set_pprof_trace' ) ) { apd_set_pprof_trace(); } $this->start_session( 'Overall' ); } function start_session( $name, $desc='' ) { $x = array_push( $this->timer_stack, $this->cur_timer ); if( isset($this->timer_stack[ $x - 1 ]) ) { $this->_suspend_timer( $this->timer_stack[ $x - 1 ] ); } $this->start_time[ $name ] = $this->get_micro_seconds(); $this->start_memory[ $name ] = $this->get_current_memory(); $this->cur_timer = $name; $this->descriptions[ $name ] = $desc; if( array_key_exists( $name, $this->internal_count ) ) { $this->internal_count[ $name ]++; } else { $this->internal_count[ $name ] = 1; } $this->stack_trace .= "Started Session '{$name}'\n"; $backtrace = debug_backtrace(); if( is_array($backtrace) AND count($backtrace) ) { $cnt = 0; foreach( array_reverse( $backtrace ) as $trace ) { $cnt++; $this->stack_trace .= "\t{$cnt}. Function '{$trace['function']}' in {$trace['file']} (line {$trace['line']})\n"; } } } function stop_session( $name ) { $this->end_time[ $name ] = $this->get_micro_seconds(); $this->end_memory[ $name ] = $this->get_current_memory(); if( !array_key_exists( $name, $this->running_time ) ) { $this->running_time[ $name ] = $this->get_elapsed_time( $name ); } else { $this->running_time[ $name ] += $this->get_elapsed_time( $name ); } $this->cur_timer = array_pop( $this->timer_stack ); $this->stack_trace .= "Stopped Session '{$name}'\n"; if( isset($this->cur_timer) ) { $this->_resume_timer( $this->cur_timer ); } } function get_elapsed_time( $name ) { if( !array_key_exists( $name, $this->start_time ) ) { return 0; } if( array_key_exists( $name, $this->end_time ) ) { return ( $this->end_time[ $name ] - $this->start_time[ $name ] ); } else { return( $this->get_micro_seconds() - $this->start_time[ $name ] ); } } function get_total_time() { return ( $this->get_micro_seconds() - $this->init_time ); } function get_peak_memory() { if( function_exists( 'memory_get_peak_usage' ) ) { $this->peak_memory = memory_get_peak_usage(); } else { if( count( $this->start_memory ) ) { foreach( $this->start_memory as $mem_entry ) { if( $mem_entry > $this->peak_memory ) { $this->peak_memory = $mem_entry; } } } if( count( $this->end_memory ) ) { foreach( $this->end_memory as $mem_entry ) { if( $mem_entry > $this->peak_memory ) { $this->peak_memory = $mem_entry; } } } } return $this->peak_memory; } function _resume_timer( $name ) { $this->stack_trace .= "Resumed Session '{$name}'\n"; $this->start_time[ $name ] = $this->get_micro_seconds(); } function _suspend_timer( $name ) { $this->stack_trace .= "Suspended Session '{$name}'\n"; $this->end_time[ $name ] = $this->get_micro_seconds(); if( !array_key_exists( $name, $this->running_time ) ) { $this->running_time[ $name ] = $this->get_elapsed_time( $name ); } else { $this->running_time[ $name ] += $this->get_elapsed_time( $name ); } } function get_micro_seconds() { $tmp = explode( " ", microtime() ); return ( $tmp[0] + $tmp[1] ); } function get_current_memory() { if( ! function_exists( 'memory_get_usage' ) ) { return 0; } else { return memory_get_usage(); } } function format_memory( $val=0 ) { if( $val >= 1048576 ) { return ( round( ( $val / 1048576 * 100 ), 2 ) / 100 ) . 'MB'; } else if( $val >= 1024 ) { return ( round( ( $val / 1024 * 100 ), 2 ) / 100 ) . 'KB'; } else { return intval( $val ) . 'b'; } } function output_results( $display_backtrace=true, $log=false ) { $this->stop_session( 'Overall' ); $this->total_memory = $this->get_current_memory(); $timed_total = 0; $percent_total = 0; $output = null; $overall_time = $this->get_total_time(); $overall_memory = $this->get_peak_memory(); if( $log == false ) { print "
\n";
	    }
	    
	    ksort($this->descriptions);
	    
	    $output  = "============================================================================\n";
	    $output .= "                              PROFILER OUTPUT\n";
	    $output .= "============================================================================\n";
	    $output .= "Calls			Time	Memory		Routine\n";
	    $output .= "----------------------------------------------------------------------------\n";
	    
	    foreach( $this->descriptions as $key => $val )
	    {
		    $this_total		= $this->running_time[$key];
		    $this_count		= $this->internal_count[$key];
		    $this_percent	= ( $this_total / $overall_time ) * 100;
		    $this_memory	= $this->format_memory( $this->end_memory[ $key ] - $this->start_memory[ $key ] );
		    
		    $timed_total	+= $this_total;
		    $percent_total	+= $this_percent;
		    $mem_total		+= $this->end_memory[ $key ] - $this->start_memory[ $key ];
		    
		    $output .= sprintf( "%3d	%3.4f ms (%3.2f %%)  %s	 %s\n", $this_count, $this_total * 1000, $this_percent, $this_memory, $key);
	    }
	    
	    $output .= "\n";
	    
	    $missed_time	= $overall_time - $timed_total;
	    $missed_percent	= ( $missed_time / $overall_time ) * 100;
	    $percent_total	+= $missed_percent;
	    $missed_memory	= $this->format_memory( $this->total_memory - $this->init_memory - $mem_total );
	    
		$output .= sprintf( "   	 %3.4f ms (%3.2f %%)  %s  %s\n", $missed_time * 1000, $missed_percent, $missed_memory, 'Leaked' );
		
		$output .= "============================================================================\n";
		$output .= "Start Memory: " . $this->format_memory( $this->init_memory ) . "\n";
		$output .= "Total Memory: " . $this->format_memory( $this->total_memory ) . "\n";
		$output .= "Peak Memory:  " . $this->format_memory( $this->peak_memory ) . "\n";
		$output .= "============================================================================\n";
		
		$output .= sprintf( "       %3.4f ms (%3.2f %%)  %s  %s\n", $timed_total * 1000, $pecent_total, $this->format_memory( $this->total_memory ), 'OVERALL TIME' );

		$output .= "============================================================================\n";

		if( $display_backtrace == true )
		{
			$output .= "Backtrace\n";
			$output .= $this->stack_trace;
		}
		
		if( $log == false )
		{
			print $output . '
'; } else { return $output; } } } ?>