[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/Benchmark/ -> Profiler.php (source)

   1  <?php
   2  //
   3  // +----------------------------------------------------------------------+
   4  // | PEAR :: Benchmark                                                    |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 2002-2006 Matthias Englert <Matthias.Englert@gmx.de>.  |
   7  // +----------------------------------------------------------------------+
   8  // | This source file is subject to the New BSD license, That is bundled  |
   9  // | with this package in the file LICENSE, and is available through      |
  10  // | the world-wide-web at                                                |
  11  // | http://www.opensource.org/licenses/bsd-license.php                   |
  12  // | If you did not receive a copy of the new BSDlicense and are unable   |
  13  // | to obtain it through the world-wide-web, please send a note to       |
  14  // | license@php.net so we can mail you a copy immediately.               |
  15  // +----------------------------------------------------------------------+
  16  //
  17  // $Id: Profiler.php,v 1.19 2006/03/01 19:26:09 anant Exp $
  18  //
  19  
  20  require_once  'PEAR.php';
  21  
  22  /**
  23   * Provides timing and profiling information.
  24   *
  25   * Example 1: Automatic profiling start, stop, and output.
  26   *
  27   * <code>
  28   * <?php
  29   * require_once 'Benchmark/Profiler.php';
  30   *
  31   * $profiler = new Benchmark_Profiler(TRUE);
  32   *
  33   * function myFunction() {
  34   *     global $profiler;
  35   *     $profiler->enterSection('myFunction');
  36   *     //do something
  37   *     $profiler->leaveSection('myFunction');
  38   *     return;
  39   * }
  40   *
  41   * //do something
  42   * myFunction();
  43   * //do more
  44   * ?>
  45   * </code>
  46   *
  47   * Example 2: Manual profiling start, stop, and output.
  48   *
  49   * <code>
  50   * <?php
  51   * require_once 'Benchmark/Profiler.php';
  52   *
  53   * $profiler = new Benchmark_Profiler();
  54   *
  55   * function myFunction() {
  56   *     global $profiler;
  57   *     $profiler->enterSection('myFunction');
  58   *     //do something
  59   *     $profiler->leaveSection('myFunction');
  60   *     return;
  61   * }
  62   *
  63   * $profiler->start();
  64   * //do something
  65   * myFunction();
  66   * //do more
  67   * $profiler->stop();
  68   * $profiler->display();
  69   * ?>
  70   * </code>
  71   *
  72   * @author    Matthias Englert <Matthias.Englert@gmx.de>
  73   * @copyright Copyright &copy; 2002-2005 Matthias Englert <Matthias.Englert@gmx.de>
  74   * @license   http://www.php.net/license/3_0.txt The PHP License, Version 3.0
  75   * @category  Benchmarking
  76   * @package   Benchmark
  77   * @since     1.2.0
  78   */
  79  class Benchmark_Profiler extends PEAR {
  80      /**
  81       * Contains the total ex. time of each section
  82       *
  83       * @var    array
  84       * @access private
  85       */
  86      var $_sections = array();
  87  
  88      /**
  89       * Calling stack
  90       *
  91       * @var    array
  92       * @access private
  93       */
  94      var $_stack = array();
  95  
  96      /**
  97       * Notes how often a section was entered
  98       *
  99       * @var    array
 100       * @access private
 101       */
 102      var $_numberOfCalls = array();
 103  
 104      /**
 105       * Notes for each section how much time is spend in sub-sections
 106       *
 107       * @var    array
 108       * @access private
 109       */
 110      var $_subSectionsTime = array();
 111  
 112      /**
 113       * Notes for each section how often it calls which section
 114       *
 115       * @var    array
 116       * @access private
 117       */
 118      var $_calls = array();
 119  
 120      /**
 121       * Notes for each section how often it was called by which section
 122       *
 123       * @var    array
 124       * @access private
 125       */
 126      var $_callers = array();
 127  
 128      /**
 129       * Auto-starts and stops profiler
 130       *
 131       * @var    boolean
 132       * @access private
 133       */
 134      var $_auto = FALSE;
 135  
 136      /**
 137       * Max marker name length for non-html output
 138       *
 139       * @var    integer
 140       * @access private
 141       */
 142      var $_maxStringLength = 0;
 143  
 144      /**
 145       * Constructor, starts profiling recording
 146       *
 147       * @access public
 148       */
 149      function Benchmark_Profiler($auto = FALSE) {
 150          $this->_auto = $auto;
 151  
 152          if ($this->_auto) {
 153              $this->start();
 154          }
 155  
 156          $this->PEAR();
 157      }
 158  
 159      /**
 160       * Destructor, stops profiling recording
 161       *
 162       * @access private
 163       */
 164      function _Benchmark_Profiler() {
 165          if (isset($this->_auto) && $this->_auto) {
 166              $this->stop();
 167              $this->display();
 168          }
 169      }
 170  
 171      /**
 172       * Returns profiling informations for a given section.
 173       *
 174       * @param  string $section
 175       * @return array
 176       * @access public
 177       */
 178      function getSectionInformations($section = 'Global') {
 179          if (isset($this->_sections[$section])) {
 180              $calls = array();
 181  
 182              if (isset($this->_calls[$section])) {
 183                  $calls = $this->_calls[$section];
 184              }
 185  
 186              $callers = array();
 187  
 188              if (isset($this->_callers[$section])) {
 189                  $callers = $this->_callers[$section];
 190              }
 191  
 192              $informations = array();
 193  
 194              $informations['time']       = $this->_sections[$section];
 195              if (isset($this->_sections['Global'])) {
 196                  $informations['percentage'] = number_format(100 * $this->_sections[$section] / $this->_sections['Global'], 2, '.', '');
 197              } else {
 198                  $informations['percentage'] = 'N/A';
 199              }
 200              $informations['calls']      = $calls;
 201              $informations['num_calls']  = $this->_numberOfCalls[$section];
 202              $informations['callers']    = $callers;
 203  
 204                if (isset($this->_subSectionsTime[$section])) {
 205                  $informations['netto_time'] = $this->_sections[$section] - $this->_subSectionsTime[$section];
 206                } else {
 207                  $informations['netto_time'] = $this->_sections[$section];
 208                }
 209  
 210              return $informations;
 211          } else {
 212              $this->raiseError("The section '$section' does not exists.\n", NULL, PEAR_ERROR_TRIGGER, E_USER_WARNING);
 213          }
 214      }
 215  
 216      /**
 217       * Returns profiling informations for all sections.
 218       *
 219       * @return array
 220       * @access public
 221       */
 222      function getAllSectionsInformations() {
 223          $informations = array();
 224  
 225          foreach($this->_sections as $section => $time) {
 226              $informations[$section] = $this->getSectionInformations($section);
 227          }
 228  
 229          return $informations;
 230      }
 231  
 232      /**
 233       * Returns formatted profiling information.
 234       *
 235       * @param  string output format (auto, plain or html), default auto
 236       * @see    display()
 237       * @access private
 238       */
 239      function _getOutput($format) {
 240          
 241          /* Quickly find out the maximun length: Ineffecient, but will do for now! */
 242          $informations = $this->getAllSectionsInformations();
 243          $names = array_keys($informations);
 244          
 245          $maxLength = 0;
 246          foreach ($names as $name)
 247          {
 248              if ($maxLength < strlen($name)) {
 249                  $maxLength = strlen($name);
 250              }
 251          }
 252          $this->_maxStringLength = $maxLength;
 253  
 254          if ($format == 'auto') {
 255              if (function_exists('version_compare') &&
 256                  version_compare(phpversion(), '4.1', 'ge')) {
 257                  $format = isset($_SERVER['SERVER_PROTOCOL']) ? 'html' : 'plain';
 258              } else {
 259                  global $HTTP_SERVER_VARS;
 260                  $format = isset($HTTP_SERVER_VARS['SERVER_PROTOCOL']) ? 'html' : 'plain';
 261              }
 262          }
 263  
 264          if ($format == 'html') {
 265              $out = '<table style="border: 1px solid #000000; ">'."\n";
 266              $out .=
 267                  '<tr><td>&nbsp;</td><td align="center"><b>total ex. time</b></td>'.
 268                  '<td align="center"><b>netto ex. time</b></td>'.
 269                  '<td align="center"><b>#calls</b></td><td align="center"><b>%</b></td>'.
 270                  '<td align="center"><b>calls</b></td><td align="center"><b>callers</b></td></tr>'.
 271                  "\n";
 272          } else {
 273              $dashes = $out = str_pad("\n", ($this->_maxStringLength + 75), '-', STR_PAD_LEFT);
 274              $out .= str_pad('Section', $this->_maxStringLength + 10);
 275              $out .= str_pad("Total Ex Time", 22);
 276              $out .= str_pad("Netto Ex Time", 22);
 277              $out .= str_pad("#Calls", 10);
 278              $out .= "Percentage\n";
 279              $out .= $dashes;
 280          }
 281             
 282          foreach($informations as $name => $values) {
 283              $percentage = $values['percentage'];
 284              $calls_str = "";
 285  
 286              foreach($values['calls'] as $key => $val) {
 287                  if ($calls_str) {
 288                      $calls_str .= ", ";
 289                  }
 290  
 291                  $calls_str .= "$key ($val)";
 292              }
 293  
 294              $callers_str = "";
 295  
 296              foreach($values['callers'] as $key => $val) {
 297                  if ($callers_str) {
 298                      $callers_str .= ", ";
 299                      }
 300  
 301                  $callers_str .= "$key ($val)";
 302              }
 303  
 304              if ($format == 'html') {
 305                  $out .= "<tr><td><b>$name</b></td><td>{$values['time']}</td><td>{$values['netto_time']}</td><td>{$values['num_calls']}</td>";
 306                  if (is_numeric($values['percentage'])) {
 307                      $out .= "<td align=\"right\">{$values['percentage']}%</td>\n";
 308                  } else {
 309                      $out .= "<td align=\"right\">{$values['percentage']}</td>\n";
 310                  }
 311                  $out .= "<td>$calls_str</td><td>$callers_str</td></tr>";
 312              } else {
 313                  $out .= str_pad($name, $this->_maxStringLength + 10);
 314                  $out .= str_pad($values['time'], 22);
 315                  $out .= str_pad($values['netto_time'], 22);
 316                  $out .= str_pad($values['num_calls'], 10);
 317                  if (is_numeric($values['percentage'])) {
 318                      $out .= str_pad($values['percentage']."%\n", 8, ' ', STR_PAD_LEFT);
 319                  } else {
 320                      $out .= str_pad($values['percentage']."\n", 8, ' ', STR_PAD_LEFT);
 321                  }
 322              }
 323          }
 324          
 325          if ($format == 'html') {
 326              return $out . '</table>';
 327          } else {
 328              return $out;
 329          }
 330      }
 331  
 332      /**
 333       * Returns formatted profiling information.
 334       *
 335       * @param  string output format (auto, plain or html), default auto
 336       * @access public
 337       */
 338      function display($format = 'auto') {
 339          echo $this->_getOutput($format);
 340      }
 341  
 342      /**
 343       * Enters "Global" section.
 344       *
 345       * @see    enterSection(), stop()
 346       * @access public
 347       */
 348      function start() {
 349          $this->enterSection('Global');
 350      }
 351  
 352      /**
 353       * Leaves "Global" section.
 354       *
 355       * @see    leaveSection(), start()
 356       * @access public
 357       */
 358      function stop() {
 359          $this->leaveSection('Global');
 360      }
 361  
 362      /**
 363       * Enters code section.
 364       *
 365       * @param  string  name of the code section
 366       * @see    start(), leaveSection()
 367       * @access public
 368       */
 369      function enterSection($name) {
 370          if (count($this->_stack)) {
 371              if (isset($this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]])) {
 372                  $this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]]++;
 373              } else {
 374                  $this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]] = 1;
 375              }
 376  
 377              if (isset($this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name])) {
 378                  $this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name]++;
 379              } else {
 380                  $this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name] = 1;
 381              }
 382          } else {
 383              if ($name != 'Global') {
 384                  $this->raiseError("tried to enter section ".$name." but profiling was not started\n", NULL, PEAR_ERROR_DIE);
 385              }
 386          }
 387  
 388          if (isset($this->_numberOfCalls[$name])) {
 389              $this->_numberOfCalls[$name]++;
 390          } else {
 391              $this->_numberOfCalls[$name] = 1;
 392          }
 393  
 394          array_push($this->_stack, array("name" => $name, "time" => $this->_getMicrotime()));
 395      }
 396  
 397      /**
 398       * Leaves code section.
 399       *
 400       * @param  string  name of the marker to be set
 401       * @see     stop(), enterSection()
 402       * @access public
 403       */
 404      function leaveSection($name) {
 405          $microtime = $this->_getMicrotime();
 406  
 407          if (!count($this->_stack)) {
 408              $this->raiseError("tried to leave section ".$name." but profiling was not started\n", NULL, PEAR_ERROR_DIE);
 409          }
 410  
 411          $x = array_pop($this->_stack);
 412  
 413          if ($x["name"] != $name) {
 414              $this->raiseError("reached end of section $name but expecting end of " . $x["name"]."\n", NULL, PEAR_ERROR_DIE);
 415          }
 416  
 417          if (isset($this->_sections[$name])) {
 418              $this->_sections[$name] += $microtime - $x["time"];
 419          } else {
 420              $this->_sections[$name] = $microtime - $x["time"];
 421          }
 422  
 423          $parent = array_pop($this->_stack);
 424  
 425            if (isset($parent)) {
 426              if (isset($this->_subSectionsTime[$parent['name']])) {
 427                  $this->_subSectionsTime[$parent['name']] += $microtime - $x['time'];
 428              } else {
 429                  $this->_subSectionsTime[$parent['name']] = $microtime - $x['time'];
 430              }
 431  
 432              array_push($this->_stack, $parent);
 433          }
 434      }
 435  
 436      /**
 437       * Wrapper for microtime().
 438       *
 439       * @return float
 440       * @access private
 441       * @since  1.3.0
 442       */
 443      function _getMicrotime() {
 444          $microtime = explode(' ', microtime());
 445          return $microtime[1] . substr($microtime[0], 1);
 446      }
 447  }


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7