Benchmark
[ class tree: Benchmark ] [ index: Benchmark ] [ all elements ]

Source for file Profiler.php

Documentation is available at Profiler.php

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

Documentation generated on Mon, 11 Mar 2019 14:18:40 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.