PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/phase3/profileinfo.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 328 lines | 293 code | 10 blank | 25 comment | 4 complexity | 3074ce315b7f4501189034c2c79190c3 MD5 | raw file
  1. <?php
  2. /**
  3. * Show profiling data.
  4. *
  5. * Copyright 2005 Kate Turner.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. *
  25. * @file
  26. */
  27. ini_set( 'zlib.output_compression', 'off' );
  28. $wgEnableProfileInfo = $wgProfileToDatabase = false;
  29. if ( isset( $_SERVER['MW_COMPILED'] ) ) {
  30. require ( 'phase3/includes/WebStart.php' );
  31. } else {
  32. require ( dirname( __FILE__ ) . '/includes/WebStart.php' );
  33. }
  34. header( 'Content-Type: text/html; charset=utf-8' );
  35. ?>
  36. <html>
  37. <head>
  38. <title>Profiling data</title>
  39. <style type="text/css">
  40. th {
  41. text-align: left;
  42. border-bottom: solid 1px black;
  43. }
  44. th, td {
  45. padding-left: 0.5em;
  46. padding-right: 0.5em;
  47. }
  48. td.timep, td.memoryp, td.count, td.cpr, td.tpc, td.mpc, td.tpr, td.mpr {
  49. text-align: right;
  50. }
  51. td.timep, td.tpc, td.tpr {
  52. background-color: #fffff0;
  53. }
  54. td.memoryp, td.mpc, td.mpr {
  55. background-color: #f0f8ff;
  56. }
  57. td.count, td,cpr {
  58. background-color: #f0fff0;
  59. }
  60. td.name {
  61. background-color: #f9f9f9;
  62. }
  63. </style>
  64. </head>
  65. <body>
  66. <?php
  67. if ( !$wgEnableProfileInfo ) {
  68. echo "<p>Disabled</p>\n";
  69. echo "</body></html>";
  70. exit( 1 );
  71. }
  72. $dbr = wfGetDB( DB_SLAVE );
  73. if( !$dbr->tableExists( 'profileinfo' ) ) {
  74. echo "<p>No 'profileinfo' table exists, so we can't show you anything.</p>\n";
  75. echo "<p>If you want to log profiling data, create the table using "
  76. . "<tt>maintenance/archives/patch-profiling.sql</tt> and enable "
  77. . "<tt>\$wgProfileToDatabase</tt>.</p>\n";
  78. echo "</body></html>";
  79. exit( 1 );
  80. }
  81. $expand = array();
  82. if ( isset( $_REQUEST['expand'] ) )
  83. foreach( explode( ',', $_REQUEST['expand'] ) as $f )
  84. $expand[$f] = true;
  85. class profile_point {
  86. var $name;
  87. var $count;
  88. var $time;
  89. var $children;
  90. static $totaltime, $totalmemory, $totalcount;
  91. function __construct( $name, $count, $time, $memory ) {
  92. $this->name = $name;
  93. $this->count = $count;
  94. $this->time = $time;
  95. $this->memory = $memory;
  96. $this->children = array();
  97. }
  98. function add_child( $child ) {
  99. $this->children[] = $child;
  100. }
  101. function display( $expand, $indent = 0.0 ) {
  102. usort( $this->children, 'compare_point' );
  103. $ex = isset( $expand[$this->name()] );
  104. if ( !$ex ) {
  105. if ( count( $this->children ) ) {
  106. $url = getEscapedProfileUrl( false, false, $expand + array( $this->name() => true ) );
  107. $extet = " <a href=\"$url\">[+]</a>";
  108. } else {
  109. $extet = '';
  110. }
  111. } else {
  112. $e = array();
  113. foreach ( $expand as $name => $ep ) {
  114. if ( $name != $this->name() ) {
  115. $e += array( $name => $ep );
  116. }
  117. }
  118. $extet = " <a href=\"" . getEscapedProfileUrl( false, false, $e ) . "\">[–]</a>";
  119. }
  120. ?>
  121. <tr>
  122. <td class="name" style="padding-left: <?php echo $indent ?>em;">
  123. <?php echo htmlspecialchars( $this->name() ) . $extet ?>
  124. </td>
  125. <td class="timep"><?php echo @wfPercent( $this->time() / self::$totaltime * 100 ) ?></td>
  126. <td class="memoryp"><?php echo @wfPercent( $this->memory() / self::$totalmemory * 100 ) ?></td>
  127. <td class="count"><?php echo $this->count() ?></td>
  128. <td class="cpr"><?php echo round( sprintf( '%.2f', $this->callsPerRequest() ), 2 ) ?></td>
  129. <td class="tpc"><?php echo round( sprintf( '%.2f', $this->timePerCall() ), 2 ) ?></td>
  130. <td class="mpc"><?php echo round( sprintf( '%.2f' ,$this->memoryPerCall() / 1024 ), 2 ) ?></td>
  131. <td class="tpr"><?php echo @round( sprintf( '%.2f', $this->time() / self::$totalcount ), 2 ) ?></td>
  132. <td class="mpr"><?php echo @round( sprintf( '%.2f' ,$this->memory() / self::$totalcount / 1024 ), 2 ) ?></td>
  133. </tr>
  134. <?php
  135. if ( $ex ) {
  136. foreach ( $this->children as $child ) {
  137. $child->display( $expand, $indent + 2 );
  138. }
  139. }
  140. }
  141. function name() {
  142. return $this->name;
  143. }
  144. function count() {
  145. return $this->count;
  146. }
  147. function time() {
  148. return $this->time;
  149. }
  150. function memory() {
  151. return $this->memory;
  152. }
  153. function timePerCall() {
  154. return @( $this->time / $this->count );
  155. }
  156. function memoryPerCall() {
  157. return @( $this->memory / $this->count );
  158. }
  159. function callsPerRequest() {
  160. return @( $this->count / self::$totalcount );
  161. }
  162. function timePerRequest() {
  163. return @( $this->time / self::$totalcount );
  164. }
  165. function memoryPerRequest() {
  166. return @( $this->memory / self::$totalcount );
  167. }
  168. function fmttime() {
  169. return sprintf( "%5.02f", $this->time );
  170. }
  171. };
  172. function compare_point( $a, $b ) {
  173. global $sort;
  174. switch ( $sort ) {
  175. case "name":
  176. return strcmp( $a->name(), $b->name() );
  177. case "time":
  178. return $a->time() > $b->time() ? -1 : 1;
  179. case "memory":
  180. return $a->memory() > $b->memory() ? -1 : 1;
  181. case "count":
  182. return $a->count() > $b->count() ? -1 : 1;
  183. case "time_per_call":
  184. return $a->timePerCall() > $b->timePerCall() ? -1 : 1;
  185. case "memory_per_call":
  186. return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1;
  187. case "calls_per_req":
  188. return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1;
  189. case "time_per_req":
  190. return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1;
  191. case "memory_per_req":
  192. return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1;
  193. }
  194. }
  195. $sorts = array( 'time', 'memory', 'count', 'calls_per_req', 'name',
  196. 'time_per_call', 'memory_per_call', 'time_per_req', 'memory_per_req' );
  197. $sort = 'time';
  198. if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) )
  199. $sort = $_REQUEST['sort'];
  200. $res = $dbr->select( 'profiling', '*', array(), 'profileinfo.php', array( 'ORDER BY' => 'pf_name ASC' ) );
  201. if (isset( $_REQUEST['filter'] ) )
  202. $filter = $_REQUEST['filter'];
  203. else
  204. $filter = '';
  205. ?>
  206. <form method="get" action="profileinfo.php">
  207. <p>
  208. <input type="text" name="filter" value="<?php echo htmlspecialchars($filter)?>"/>
  209. <input type="hidden" name="sort" value="<?php echo htmlspecialchars($sort)?>"/>
  210. <input type="hidden" name="expand" value="<?php echo htmlspecialchars(implode(",", array_keys($expand)))?>"/>
  211. <input type="submit" value="Filter" />
  212. </p>
  213. </form>
  214. <table cellspacing="0" border="1">
  215. <tr id="top">
  216. <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ) ?>">Name</a></th>
  217. <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ) ?>">Time (%)</a></th>
  218. <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ) ?>">Memory (%)</a></th>
  219. <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ) ?>">Count</a></th>
  220. <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ) ?>">Calls/req</a></th>
  221. <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ) ?>">ms/call</a></th>
  222. <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ) ?>">kb/call</a></th>
  223. <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ) ?>">ms/req</a></th>
  224. <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ) ?>">kb/req</a></th>
  225. </tr>
  226. <?php
  227. profile_point::$totaltime = 0.0;
  228. profile_point::$totalcount = 0;
  229. profile_point::$totalmemory = 0.0;
  230. function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
  231. global $filter, $sort, $expand;
  232. if ( $_expand === false )
  233. $_expand = $expand;
  234. return htmlspecialchars(
  235. '?' .
  236. wfArrayToCGI( array(
  237. 'filter' => $_filter ? $_filter : $filter,
  238. 'sort' => $_sort ? $_sort : $sort,
  239. 'expand' => implode( ',', array_keys( $_expand ) )
  240. ) )
  241. );
  242. }
  243. $points = array();
  244. $queries = array();
  245. $sqltotal = 0.0;
  246. $last = false;
  247. foreach( $res as $o ) {
  248. $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory );
  249. if( $next->name() == '-total' ) {
  250. profile_point::$totaltime = $next->time();
  251. profile_point::$totalcount = $next->count();
  252. profile_point::$totalmemory = $next->memory();
  253. }
  254. if ( $last !== false ) {
  255. if ( preg_match( "/^".preg_quote( $last->name(), "/" )."/", $next->name() ) ) {
  256. $last->add_child($next);
  257. continue;
  258. }
  259. }
  260. $last = $next;
  261. if ( preg_match( "/^query: /", $next->name() ) || preg_match( "/^query-m: /", $next->name() ) ) {
  262. $sqltotal += $next->time();
  263. $queries[] = $next;
  264. } else {
  265. $points[] = $next;
  266. }
  267. }
  268. $s = new profile_point( "SQL Queries", 0, $sqltotal, 0, 0 );
  269. foreach ( $queries as $q )
  270. $s->add_child($q);
  271. $points[] = $s;
  272. usort( $points, "compare_point" );
  273. foreach ( $points as $point ) {
  274. if ( strlen( $filter ) && !strstr( $point->name(), $filter ) )
  275. continue;
  276. $point->display( $expand );
  277. }
  278. ?>
  279. </table>
  280. <p>Total time: <tt><?php printf("%5.02f", profile_point::$totaltime) ?></tt></p>
  281. <p>Total memory: <tt><?php printf("%5.02f", profile_point::$totalmemory / 1024 ) ?></tt></p>
  282. </body>
  283. </html>