Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpif ( $argc <= 1 || $argc > 4 ){showUsage();}$fileName = $argv[1];$sortKey = 'time-own';$elements = 25;if ( $argc > 2 ){$sortKey = $argv[2];if ( !in_array( $sortKey, array( 'calls', 'time-inclusive', 'memory-inclusive', 'time-own', 'memory-own' ) ) ){showUsage();}}if ( $argc > 3 ){$elements = (int) $argv[3];}$o = new drXdebugTraceFileParser( $argv[1] );$o->parse();$functions = $o->getFunctions( $sortKey );// find longest function name$maxLen = 0;foreach( $functions as $name => $f ){if ( strlen( $name ) > $maxLen ){$maxLen = strlen( $name );}}echo "Showing the {$elements} most costly calls sorted by '{$sortKey}'.\n\n";echo " ", str_repeat( ' ', $maxLen - 8 ), " Inclusive Own\n";echo "function", str_repeat( ' ', $maxLen - 8 ), "#calls time memory time memory\n";echo "--------", str_repeat( '-', $maxLen - 8 ), "----------------------------------------\n";// display functions$c = 0;foreach( $functions as $name => $f ){$c++;if ( $c > $elements ){break;}printf( "%-{$maxLen}s %5d %3.4f %8d %3.4f %8d\n",$name, $f['calls'],$f['time-inclusive'], $f['memory-inclusive'],$f['time-own'], $f['memory-own'] );}function showUsage(){echo "usage:\n\tphp run-cli tracefile [sortkey] [elements]\n\n";echo "Allowed sortkeys:\n\tcalls, time-inclusive, memory-inclusive, time-own, memory-own\n";die();}class drXdebugTraceFileParser{protected $handle;/*** Stores the last function, time and memory for the entry point per* stack depth. int=>array(string, float, int).*/protected $stack;/*** Stores per function the total time and memory increases and calls* string=>array(float, int, int)*/protected $functions;/*** Stores which functions are on the stack*/protected $stackFunctions;public function __construct( $fileName ){$this->handle = fopen( $fileName, 'r' );if ( !$this->handle ){throw new Exception( "Can't open '$fileName'" );}$this->stack[-1] = array( '', 0, 0, 0, 0 );$this->stack[ 0] = array( '', 0, 0, 0, 0 );$this->stackFunctions = array();}public function parse(){echo "\nparsing...\n";$c = 0;$size = fstat( $this->handle );$size = $size['size'];$read = 0;while ( !feof( $this->handle ) ){$buffer = fgets( $this->handle, 4096 );$read += strlen( $buffer );$this->parseLine( $buffer );$c++;if ( $c % 25000 === 0 ){printf( " (%5.2f%%)\n", ( $read / $size ) * 100 );}}echo "\nDone.\n\n";}private function parseLine( $line ){/*if ( preg_match( '@^Version: (.*)@', $line, $matches ) ){}else if ( preg_match( '@^File format: (.*)@', $line, $matches ) ){}else if ( preg_match( '@^TRACE.*@', $line, $matches ) ){}else // assume a normal line*/{$parts = explode( "\t", $line );if ( count( $parts ) < 5 ){return;}$depth = $parts[0];$funcNr = $parts[1];$time = $parts[3];$memory = $parts[4];if ( $parts[2] == '0' ) // function entry{$funcName = $parts[5];$intFunc = $parts[6];$this->stack[$depth] = array( $funcName, $time, $memory, 0, 0 );array_push( $this->stackFunctions, $funcName );}else if ( $parts[2] == '1' ) // function exit{list( $funcName, $prevTime, $prevMem, $nestedTime, $nestedMemory ) = $this->stack[$depth];// collapse data onto functions array$dTime = $time - $prevTime;$dMemory = $memory - $prevMem;$this->stack[$depth - 1][3] += $dTime;$this->stack[$depth - 1][4] += $dMemory;array_pop( $this->stackFunctions );$this->addToFunction( $funcName, $dTime, $dMemory, $nestedTime, $nestedMemory );}}}protected function addToFunction( $function, $time, $memory, $nestedTime, $nestedMemory ){if ( !isset( $this->functions[$function] ) ){$this->functions[$function] = array( 0, 0, 0, 0, 0 );}$elem = &$this->functions[$function];$elem[0]++;if ( !in_array( $function, $this->stackFunctions ) ) {$elem[1] += $time;$elem[2] += $memory;$elem[3] += $nestedTime;$elem[4] += $nestedMemory;}}public function getFunctions( $sortKey = null ){$result = array();foreach ( $this->functions as $name => $function ){$result[$name] = array('calls' => $function[0],'time-inclusive' => $function[1],'memory-inclusive' => $function[2],'time-children' => $function[3],'memory-children' => $function[4],'time-own' => $function[1] - $function[3],'memory-own' => $function[2] - $function[4]);}if ( $sortKey !== null ){uasort( $result,function( $a, $b ) use ( $sortKey ){return ( $a[$sortKey] > $b[$sortKey] ) ? -1 : ( $a[$sortKey] < $b[$sortKey] ? 1 : 0 );});}return $result;}}?>