/upload/develop/profiler/profiler_dbg.php

http://torrentpier2.googlecode.com/ · PHP · 373 lines · 178 code · 33 blank · 162 comment · 7 complexity · 114a681186a54f0527e92069ca76a54f MD5 · raw file

  1. <?php
  2. /*
  3. Original from http://forum.dklab.ru/php/advises/ProfaylerForScriptsOnPhp.html
  4. completely rewritten by Meithar
  5. Usage of profiler script:
  6. 1. Setup 'php_dbg' [http://dd.cron.ru/dbg/] module on your php.ini
  7. 2. Run DBG Listener
  8. 3. Include this file at the end of you script
  9. 4. To enable profiling use you script with parameters: ?DBGSESSID=1@clienthost:7869;p=1
  10. P.S.: see parameters bellow
  11. 5. To disable profiling use you script with parameters: ?DBGSESSID=-1
  12. P.S. All DBGSESSID parameters stored in cookie. You must run in once to enable, and
  13. once to disable.
  14. *****************************************************************************
  15. DBGSESSID Usage:
  16. *****************************************************************************
  17. DBGSESSID=nnn[@host][:port][;{flags}]
  18. where
  19. nnn - is session ID (any positive number or zero)
  20. NOTE: negative values prohibit debug session to run and drops cookie
  21. host - is host name or IP address of the host where your run PHPED IDE.
  22. You may set clienthost which is a keyword, in this case debugger looks for
  23. proper client IP address automatically.
  24. flags - set of the following flags delimited with commas:
  25. s=skip - skip number of HTTP requests before actual session should run
  26. d={0|1} - start debug session
  27. p={0|1} - start profiler session
  28. For example:
  29. DBGSESSID=1@clienthost:7869;d=1,p=1
  30. DBGSESSID=1;d=1,p=0
  31. DBGSESSID=1:7869;d=1,p=0,s=5
  32. On/Off:
  33. javascript: document.cookie = 'DBGSESSID=' + escape('1;d=1,p=0') + '; path=/'; document.execCommand('refresh');
  34. javascript: document.cookie = 'DBGSESSID=' + escape('1;d=0,p=0') + '; path=/'; document.execCommand('refresh');
  35. javascript:location.href=location.protocol+'//'+location.hostname+location.pathname+'?DBGSESSID=1;d=1,p=0'
  36. javascript:location.href=location.protocol+'//'+location.hostname+location.pathname+'?DBGSESSID=-1
  37. *****************************************************************************
  38. PHP_DBG Module functions
  39. *****************************************************************************
  40. ---------------------------------------------------
  41. get all profiler results
  42. ---------------------------------------------------
  43. int dbg_get_profiler_results(array &$results);
  44. return int: count of $results
  45. $results = array(
  46. 'mod_no' => array(),
  47. 'line_no' => array(),
  48. 'hit_count' => array(),
  49. 'tm_max' => array(),
  50. 'tm_min' => array(),
  51. 'tm_sum' => array(),
  52. );
  53. ---------------------------------------------------
  54. get all modules name
  55. ---------------------------------------------------
  56. int dbg_get_all_module_names(array &$results);
  57. return int: count of $results
  58. $results = array(
  59. 'mod_no' => array(),
  60. 'mod_name' => array(),
  61. );
  62. ---------------------------------------------------
  63. get module name
  64. ---------------------------------------------------
  65. int dbg_get_module_name(int $mod_no, string &$results);
  66. return int: 0 - error
  67. 1 - success
  68. $results = module name
  69. ---------------------------------------------------
  70. get all context (function name) for given module
  71. ---------------------------------------------------
  72. int dbg_get_all_contexts(int $mod_no, array &$results);
  73. if $mod_no = 0 it returns all contexts
  74. return int: count of $results
  75. $results = array(
  76. 'ctx_no' => array(),
  77. 'mod_no' => array(),
  78. 'ctx_name' => array(),
  79. );
  80. ---------------------------------------------------
  81. get context name
  82. ---------------------------------------------------
  83. int dbg_get_context_name(int $ctx_no, string &$function_name);
  84. return int: 0 - error
  85. 1 - success
  86. $function_name = function name
  87. ---------------------------------------------------
  88. get all source lines for given module
  89. ---------------------------------------------------
  90. int dbg_get_all_source_lines(int $mod_no, array &$results);
  91. if $mod_no = 0 it returns all source lines for all contexts
  92. return int: count of $results
  93. $results = array(
  94. 'ctx_no' => array(),
  95. 'mod_no' => array(),
  96. 'line_no' => array(),
  97. );
  98. ---------------------------------------------------
  99. get context id for given module and line
  100. ---------------------------------------------------
  101. int dbg_get_source_context(int $mod_no, int $line_no, int &$ctx_no);
  102. return int: 0 - error
  103. 1 - success
  104. $ctx_no = function name
  105. */
  106. ##############################################################################
  107. class profiler_dbg extends profiler
  108. {
  109. var $min_time = 0;
  110. var $total_time = 0;
  111. // $min_time - ??????????? ????? ?????????? ??? ?????? ? ????????? ??????????? ?????????? (? ???????? ??? %)
  112. //
  113. function print_profile_data ($min_time = 0)
  114. {
  115. // Get all profiling data
  116. dbg_get_profiler_results (&$results); # prn($results);
  117. dbg_get_all_module_names (&$modules);
  118. dbg_get_all_contexts (0, &$context);
  119. dbg_get_all_source_lines (0, &$lines);
  120. $this->total_time = array_sum($results['tm_sum']);
  121. $this->min_time = strpos($min_time, '%') ? $this->total_time * floatval($min_time)/100 : floatval($min_time);
  122. $percent = ($this->total_time) ? 100/$this->total_time : 0;
  123. $module_names = $context_names = $context_lines = $profile = array();
  124. // Module names
  125. foreach ($modules['mod_no'] as $id => $module_no)
  126. {
  127. $module_names[$module_no] = $modules['mod_name'][$id];
  128. $profile[$module_no]['time'] = 0;
  129. $profile[$module_no]['.'] = array();
  130. }
  131. // Context names
  132. foreach ($context['mod_no'] as $id => $context_no)
  133. {
  134. $module_no = $context['ctx_no'][$id];
  135. $ctx_name = $context['ctx_name'][$id];
  136. $context_names[$context_no] = ($ctx_name) ? "$ctx_name()" : 'GLOBAL';
  137. $profile[$module_no]['.'][$context_no]['time'] = 0;
  138. $profile[$module_no]['.'][$context_no]['.'] = array();
  139. }
  140. // Context lines
  141. foreach ($lines['line_no'] as $id => $line_no)
  142. {
  143. $module_no = $lines['mod_no'][$id];
  144. $context_lines[$module_no][$line_no] = $lines['ctx_no'][$id];
  145. }
  146. // Build profiling data
  147. foreach ($results['line_no'] as $id => $line_no)
  148. {
  149. $module_no = $results['mod_no'][$id];
  150. $context_no = $context_lines[$module_no][$line_no];
  151. $profile[$module_no]['time'] += $results['tm_sum'][$id];
  152. $profile[$module_no]['.'][$context_no]['time'] += $results['tm_sum'][$id];
  153. if ($results['tm_sum'][$id] < $this->min_time)
  154. {
  155. continue;
  156. }
  157. $profile[$module_no]['.'][$context_no]['.'][$line_no] = array(
  158. 'time' => $results['tm_sum'][$id],
  159. 'hits' => $results['hit_count'][$id],
  160. );
  161. }
  162. // Sort profiling data: modules, contexts and lines
  163. uasort($profile, array(__CLASS__, 'sort_by_time_desc'));
  164. foreach ($profile as $module_no => $context)
  165. {
  166. uasort($profile[$module_no]['.'], array(__CLASS__, 'sort_by_time_desc'));
  167. foreach ($context['.'] as $context_no => $lines)
  168. {
  169. uasort($profile[$module_no]['.'][$context_no]['.'], array(__CLASS__, 'sort_by_time_desc'));
  170. }
  171. }
  172. // Display profiling data
  173. $colspan = 6;
  174. $row_class = 'profRow1';
  175. // Replacements for cleaning highlighted code
  176. $highlight_replacements = array(
  177. '<code>' => '',
  178. '</code>' => '',
  179. '&nbsp;' => ' ',
  180. '>&lt;?php' => '>',
  181. '?&gt;<' => '<',
  182. '>&lt;?<' => '><',
  183. '>php ' => '>',
  184. );
  185. echo '
  186. <div id="profContainer">
  187. <table>
  188. <tbody>
  189. ';
  190. // Modules
  191. foreach ($profile as $module_no => $context)
  192. {
  193. $module_path = $module_names[$module_no];
  194. $module_name = basename($module_path);
  195. $module_src = is_file($module_path) ? file($module_path) : array();
  196. $module_time = sprintf('%.4f', $context['time']);
  197. $module_perc = sprintf('%.1f', $context['time']*$percent);
  198. if ($module_time < $this->min_time)
  199. {
  200. continue;
  201. }
  202. echo '
  203. </tbody>
  204. </table>
  205. <table cellspacing="1" cellpadding="2" border="0" class="profTable">
  206. <thead>
  207. <tr>
  208. <td colspan="'. $colspan .'" class="profFile">' . "[ <b>$module_perc%</b>, $module_time sec. ] :: <b>$module_name</b> " . '</td>
  209. </tr>
  210. <tr>
  211. <td class="profHead">&nbsp;&nbsp;%&nbsp;&nbsp;</td>
  212. <td class="profHead">&nbsp;time&nbsp;</td>
  213. <td class="profHead">&nbsp;&nbsp;avg&nbsp;&nbsp;</td>
  214. <td class="profHead">&nbsp;hits&nbsp;</td>
  215. <td class="profHead">&nbsp;line&nbsp;</td>
  216. <td class="profHead" width="100%" style="text-align: left;"> source </td>
  217. </tr>
  218. </thead>
  219. <tbody>
  220. '."\n";
  221. // Context
  222. foreach ($context['.'] as $context_no => $lines)
  223. {
  224. $context_name = $context_names[$context_no];
  225. $context_time = $this->get_ms($lines['time']);
  226. $context_perc = sprintf('%.2f', $lines['time']*$percent);
  227. $row_class = ($row_class == 'profRow1') ? 'profRow2' : 'profRow1';
  228. if ($lines['time'] < $this->min_time)
  229. {
  230. continue;
  231. }
  232. echo '
  233. <tr>
  234. <td colspan="2" class="profFunc funcTime">'. "<b>$context_perc%</b>" .'</td>
  235. <td colspan="2" class="profFunc funcTime">'. "<b>$context_time</b> ms" .'</td>
  236. <td colspan="'. ($colspan-4) .'" class="profFunc funcName">'. $context_name .'</td>
  237. </tr>
  238. ';
  239. // Lines
  240. foreach ($lines['.'] as $line_no => $data)
  241. {
  242. $line_perc = $data['time']*$percent;
  243. $line_perc = ($line_perc > 0.05) ? sprintf('%.1f', $line_perc) : '';
  244. $line_hits = ($data['hits'] != 1) ? $data['hits'] : '';
  245. $line_link = '<a class="srcOpen" href="#" onClick="OpenInEditor(\''. addslashes($module_path) ."', $line_no); return false;\">". $line_no .'</a>';
  246. $line_time_sum = $this->get_ms($data['time']);
  247. $line_time_avg = ($line_hits) ? $this->get_ms($data['time']/$line_hits, 3) : '';
  248. $perc_class = 'perc';
  249. if ($line_perc > 5) $perc_class .= ' high5';
  250. elseif ($line_perc > 3) $perc_class .= ' high3';
  251. elseif ($line_perc > 1) $perc_class .= ' high1';
  252. if ($line_src =& $module_src[$line_no-1])
  253. {
  254. $line_src = preg_replace('#\s+#', ' ', trim($line_src));
  255. $line_src = highlight_string("<?php $line_src", true);
  256. $line_src = strtr($line_src, $highlight_replacements);
  257. }
  258. echo '
  259. <tr class="'. $row_class .'">
  260. <td class="profTD '. $perc_class .'">'. $line_perc .'</td>
  261. <td class="profTD time">'. $line_time_sum .'</td>
  262. <td class="profTD avg">'. $line_time_avg .'</td>
  263. <td class="profTD hits">'. $line_hits .'</td>
  264. <td class="profTD line">'. $line_link .'</td>
  265. <td class="profTD scr" nowrap="nowrap">'. $line_src .'</td>
  266. </tr>
  267. '."\n";
  268. } // Lines
  269. } // Context
  270. } // Modules
  271. echo '
  272. </tbody></table>
  273. <table cellspacing="1" cellpadding="2" border="0" class="profTable">
  274. <tr>
  275. <td class="files">
  276. <div><b>[ '. count($modules['mod_name']) .' files, '. sprintf('%.3f', $this->total_time) .' sec. ]</b></div>
  277. <div>'. join('<br />', $modules['mod_name']) .'</div>
  278. </td>
  279. </tr>
  280. </table>
  281. </div>
  282. <br clear="all" />
  283. ';
  284. }
  285. function get_ms ($time, $precision = 2)
  286. {
  287. return ($time < 0.001) ? round($time*1000, $precision) : round($time*1000, 0);
  288. }
  289. static function sort_by_time_desc ($a, $b)
  290. {
  291. if ($a['time'] == $b['time']) return 0;
  292. return ($a['time'] > $b['time']) ? -1 : 1;
  293. }
  294. }