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 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.16 2005/11/06 09:07:10 toggg 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"NULLPEAR_ERROR_TRIGGERE_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.      * @see    display()
  236.      * @access private
  237.      */
  238.     function _getOutput({
  239.         if (function_exists('version_compare'&&
  240.             version_compare(phpversion()'4.1''ge')) {
  241.             $http = isset($_SERVER['SERVER_PROTOCOL']);
  242.         else {
  243.             global $HTTP_SERVER_VARS;
  244.             $http = isset($HTTP_SERVER_VARS['SERVER_PROTOCOL']);
  245.         }
  246.  
  247.         if ($http{
  248.             $out '<table style="border: 1px solid #000000; ">'."\n";
  249.             $out .=
  250.                 '<tr><td>&nbsp;</td><td align="center"><b>total ex. time</b></td>'.
  251.                 '<td align="center"><b>netto ex. time</b></td>'.
  252.                 '<td align="center"><b>#calls</b></td><td align="center"><b>%</b></td>'.
  253.                 '<td align="center"><b>calls</b></td><td align="center"><b>callers</b></td></tr>'.
  254.                 "\n";
  255.         else {
  256.             $dashes $out str_pad("\n"($this->_maxStringLength + 52)'-'STR_PAD_LEFT);
  257.             $out .= str_pad('section'$this->_maxStringLength);
  258.             $out .= str_pad("total ex time"22);
  259.             $out .= str_pad("netto ex time"22);
  260.             $out .= str_pad("#calls"22);
  261.             $out .= "perct\n";
  262.             $out .= $dashes;
  263.         }
  264.  
  265.         $informations $this->getAllSectionsInformations();
  266.  
  267.         foreach($informations as $name => $values{
  268.             $percentage $values['percentage'];
  269.             $calls_str "";
  270.  
  271.             foreach($values['calls'as $key => $val{
  272.                 if ($calls_str{
  273.                     $calls_str .= ", ";
  274.                 }
  275.  
  276.                 $calls_str .= "$key ($val)";
  277.             }
  278.  
  279.             $callers_str "";
  280.  
  281.             foreach($values['callers'as $key => $val{
  282.                 if ($callers_str{
  283.                     $callers_str .= ", ";
  284.                     }
  285.  
  286.                 $callers_str .= "$key ($val)";
  287.             }
  288.  
  289.             if ($http{
  290.                 $out .= "<tr><td><b>$name</b></td><td>{$values['time']}</td><td>{$values['netto_time']}</td><td>{$values['num_calls']}</td>";
  291.                 if (is_numeric($values['percentage'])) {
  292.                     $out .= "<td align=\"right\">{$values['percentage']}%</td>\n";
  293.                 else {
  294.                     $out .= "<td align=\"right\">{$values['percentage']}</td>\n";
  295.                 }
  296.                 $out .= "<td>$calls_str</td><td>$callers_str</td></tr>";
  297.             else {
  298.                 $out .= str_pad($name$this->_maxStringLength' ');
  299.                 $out .= str_pad($values['time']22);
  300.                 $out .= str_pad($values['netto_time']22);
  301.                 $out .= str_pad($values['num_calls']22);
  302.                 if (is_numeric($values['percentage'])) {
  303.                     $out .= str_pad($values['percentage']."%\n"8' 'STR_PAD_LEFT);
  304.                 else {
  305.                     $out .= str_pad($values['percentage']."\n"8' 'STR_PAD_LEFT);
  306.                 }
  307.             }
  308.         }
  309.  
  310.         return $out '</table>';
  311.     }
  312.  
  313.     /**
  314.      * Returns formatted profiling information.
  315.      *
  316.      * @access public
  317.      */
  318.     function display({
  319.         echo $this->_getOutput();
  320.     }
  321.  
  322.     /**
  323.      * Enters "Global" section.
  324.      *
  325.      * @see    enterSection(), stop()
  326.      * @access public
  327.      */
  328.     function start({
  329.         $this->enterSection('Global');
  330.     }
  331.  
  332.     /**
  333.      * Leaves "Global" section.
  334.      *
  335.      * @see    leaveSection(), start()
  336.      * @access public
  337.      */
  338.     function stop({
  339.         $this->leaveSection('Global');
  340.     }
  341.  
  342.     /**
  343.      * Enters code section.
  344.      *
  345.      * @param  string  name of the code section
  346.      * @see    start(), leaveSection()
  347.      * @access public
  348.      */
  349.     function enterSection($name{
  350.         if (count($this->_stack)) {
  351.             if (isset($this->_callers[$name][$this->_stack[count($this->_stack- 1]["name"]])) {
  352.                 $this->_callers[$name][$this->_stack[count($this->_stack- 1]["name"]]++;
  353.             else {
  354.                 $this->_callers[$name][$this->_stack[count($this->_stack- 1]["name"]] = 1;
  355.             }
  356.  
  357.             if (isset($this->_calls[$this->_stack[count($this->_stack- 1]["name"]][$name])) {
  358.                 $this->_calls[$this->_stack[count($this->_stack- 1]["name"]][$name]++;
  359.             else {
  360.                 $this->_calls[$this->_stack[count($this->_stack- 1]["name"]][$name= 1;
  361.             }
  362.         else {
  363.             if ($name != 'Global'{
  364.                 $this->raiseError("tried to enter section ".$name." but profiling was not started\n"NULLPEAR_ERROR_DIE);
  365.             }
  366.         }
  367.  
  368.         if (isset($this->_numberOfCalls[$name])) {
  369.             $this->_numberOfCalls[$name]++;
  370.         else {
  371.             $this->_numberOfCalls[$name= 1;
  372.         }
  373.  
  374.         array_push($this->_stackarray("name" => $name"time" => $this->_getMicrotime()));
  375.     }
  376.  
  377.     /**
  378.      * Leaves code section.
  379.      *
  380.      * @param  string  name of the marker to be set
  381.      * @see     stop(), enterSection()
  382.      * @access public
  383.      */
  384.     function leaveSection($name{
  385.         $microtime $this->_getMicrotime();
  386.  
  387.         if (!count($this->_stack)) {
  388.             $this->raiseError("tried to leave section ".$name." but profiling was not started\n"NULLPEAR_ERROR_DIE);
  389.         }
  390.  
  391.         $x array_pop($this->_stack);
  392.  
  393.         if ($x["name"!= $name{
  394.             $this->raiseError("reached end of section $name but expecting end of " . $x["name"]."\n"NULLPEAR_ERROR_DIE);
  395.         }
  396.  
  397.         if (isset($this->_sections[$name])) {
  398.             $this->_sections[$name+= $microtime $x["time"];
  399.         else {
  400.             $this->_sections[$name$microtime $x["time"];
  401.         }
  402.  
  403.         $parent array_pop($this->_stack);
  404.  
  405.           if (isset($parent)) {
  406.             if (isset($this->_subSectionsTime[$parent['name']])) {
  407.                 $this->_subSectionsTime[$parent['name']] += $microtime $x['time'];
  408.             else {
  409.                 $this->_subSectionsTime[$parent['name']] $microtime $x['time'];
  410.             }
  411.  
  412.             array_push($this->_stack$parent);
  413.         }
  414.     }
  415.  
  416.     /**
  417.      * Wrapper for microtime().
  418.      *
  419.      * @return float 
  420.      * @access private
  421.      * @since  1.3.0
  422.      */
  423.     function _getMicrotime({
  424.         $microtime explode(' 'microtime());
  425.         return $microtime[1substr($microtime[0]1);
  426.     }
  427. }
  428. ?>

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