[xdebug-dev] xdebug xdebug/contrib/tracefile-analyser.php xdebug/contrib/api/parser.php - Added a tracefile analysing script.

From: Derick Rethans <derick[@]derickrethans.nl>
Date: Fri, 13 Nov 2009 12:06:39 +0100

Date: Fri Nov 13 12:06:39 CET 2009
User: Derick Rethans
Directory: xdebug

Log Message:
[4.00]
- Added a tracefile analysing script.

Added files:
           xdebug/contrib/tracefile-analyser.php (new version: 1.1)
           xdebug/contrib/api/parser.php (new version: 1.1)

[FILE: /xdebug/contrib/tracefile-analyser.php]

<?php
require 'api/parser.php';

if ( $argc <= 1 || $argc > 4 )
{
        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();
}

$fileName = $argv[1];
$sortKey = 'time-own';
$elements = 25;
if ( $argc > 2 )
{
        $sortKey = $argv[2];
}
if ( $argc > 3 )
{
        $elements = (int) $argv[3];
}

$o = new drXdebugTraceFileParser( $argv[1] );
$o->parse();
$functions = $o->getFunctions( $sortKey );

echo "Showing the {$elements} most costly calls sorted by '{$sortKey}'.\n\n";

echo " Inclusive Own\n";
echo "function #calls time memory time memory\n";
echo "-------------------------------------------------------------------------------\n";

$c = 0;
foreach( $functions as $name => $f )
{
        $c++;
        if ( $c > $elements )
        {
                break;
        }
        printf( "%-39s %5d %3.4f %8d %3.4f %8d\n",
                $name, $f['calls'],
                $f['time-inclusive'], $f['memory-inclusive'],
                $f['time-own'], $f['memory-own'] );
}

[FILE: /xdebug/contrib/api/parser.php]

<?php
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;

        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 );
        }

        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( "%7d (%5.2f%%)\n", $c, ( $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 );
                        }
                        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;

                                $this->addToFunction( $funcName, $dTime, $dMemory, $nestedTime, $nestedMemory );
                        }
                }
        }

        protected function addToFunction( $function, $time, $memory, $nestedTime, $nestedMemory )
        {
                if ( !isset( $this->functions[$function] ) )
                {
                        $this->functions[$function] = array( 1, $time, $memory, $nestedTime, $nestedMemory );
                }
                else
                {
                        $elem = &$this->functions[$function];
                        $elem[0]++;
                        $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;
        }
}
?>
Received on Fri Nov 13 2009 - 12:07:21 GMT

This archive was generated by hypermail 2.2.0 : Sun Jun 24 2018 - 04:00:03 BST