00001 <?php
00002 ini_set( 'zlib.output_compression', 'off' );
00003
00004 $wgEnableProfileInfo = $wgProfileToDatabase = false;
00005
00006 require_once( './includes/WebStart.php' );
00007
00008 ?>
00009 <!--
00010 Show profiling data.
00011
00012 Copyright 2005 Kate Turner.
00013
00014 Permission is hereby granted, free of charge, to any person obtaining a copy
00015 of this software and associated documentation files (the "Software"), to deal
00016 in the Software without restriction, including without limitation the rights
00017 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00018 copies of the Software, and to permit persons to whom the Software is
00019 furnished to do so, subject to the following conditions:
00020
00021 The above copyright notice and this permission notice shall be included in
00022 all copies or substantial portions of the Software.
00023
00024 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00025 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00026 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00027 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00028 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00029 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00030 SOFTWARE.
00031
00032 -->
00033 <html>
00034 <head>
00035 <title>Profiling data</title>
00036 <style type="text/css">
00037 th {
00038 text-align: left;
00039 border-bottom: solid 1px black;
00040 }
00041
00042 th, td {
00043 padding-left: 0.5em;
00044 padding-right: 0.5em;
00045 }
00046
00047 td.timep, td.memoryp, td.count, td.cpr, td.tpc, td.mpc, td.tpr, td.mpr {
00048 text-align: right;
00049 }
00050 td.timep, td.tpc, td.tpr {
00051 background-color: #fffff0;
00052 }
00053 td.memoryp, td.mpc, td.mpr {
00054 background-color: #f0f8ff;
00055 }
00056 td.count, td,cpr {
00057 background-color: #f0fff0;
00058 }
00059 td.name {
00060 background-color: #f9f9f9;
00061 }
00062 </style>
00063 </head>
00064 <body>
00065 <?php
00066
00067 if ( !$wgEnableProfileInfo ) {
00068 echo "<p>Disabled</p>\n";
00069 echo "</body></html>";
00070 exit( 1 );
00071 }
00072
00073 $expand = array();
00074 if ( isset( $_REQUEST['expand'] ) )
00075 foreach( explode( ',', $_REQUEST['expand'] ) as $f )
00076 $expand[$f] = true;
00077
00078 class profile_point {
00079 var $name;
00080 var $count;
00081 var $time;
00082 var $children;
00083
00084 function profile_point( $name, $count, $time, $memory ) {
00085 $this->name = $name;
00086 $this->count = $count;
00087 $this->time = $time;
00088 $this->memory = $memory;
00089 $this->children = array();
00090 }
00091
00092 function add_child( $child ) {
00093 $this->children[] = $child;
00094 }
00095
00096 function display($indent = 0.0) {
00097 global $expand, $totaltime, $totalmemory, $totalcount;
00098 usort( $this->children, 'compare_point' );
00099
00100 $extet = '';
00101 if ( isset( $expand[$this->name()] ) )
00102 $ex = true;
00103 else $ex = false;
00104 if ( !$ex ) {
00105 if ( count( $this->children ) ) {
00106 $url = getEscapedProfileUrl( false, false, $expand + array( $this->name() => true ) );
00107 $extet = " <a href=\"$url\">[+]</a>";
00108 } else $extet = '';
00109 } else {
00110 $e = array();
00111 foreach ( $expand as $name => $ep )
00112 if ( $name != $this->name() )
00113 $e += array( $name => $ep );
00114
00115 $extet = " <a href=\"" . getEscapedProfileUrl( false, false, $e ) . "\">[–]</a>";
00116 }
00117 ?>
00118 <tr>
00119 <td class="name" style="padding-left: <?php echo $indent ?>em;">
00120 <?php echo htmlspecialchars( $this->name() ) . $extet ?>
00121 </td>
00122 <td class="timep"><?php echo @wfPercent( $this->time() / $totaltime * 100 ) ?></td>
00123 <td class="memoryp"><?php echo @wfPercent( $this->memory() / $totalmemory * 100 ) ?></td>
00124 <td class="count"><?php echo $this->count() ?></td>
00125 <td class="cpr"><?php echo round( sprintf( '%.2f', $this->callsPerRequest() ), 2 ) ?></td>
00126 <td class="tpc"><?php echo round( sprintf( '%.2f', $this->timePerCall() ), 2 ) ?></td>
00127 <td class="mpc"><?php echo round( sprintf( '%.2f' ,$this->memoryPerCall() / 1024 ), 2 ) ?></td>
00128 <td class="tpr"><?php echo @round( sprintf( '%.2f', $this->time() / $totalcount ), 2 ) ?></td>
00129 <td class="mpr"><?php echo @round( sprintf( '%.2f' ,$this->memory() / $totalcount / 1024 ), 2 ) ?></td>
00130 </tr>
00131 <?php
00132 if ( $ex ) {
00133 foreach ( $this->children as $child ) {
00134 $child->display( $indent + 2 );
00135 }
00136 }
00137 }
00138
00139 function name() {
00140 return $this->name;
00141 }
00142
00143 function count() {
00144 return $this->count;
00145 }
00146
00147 function time() {
00148 return $this->time;
00149 }
00150
00151 function memory() {
00152 return $this->memory;
00153 }
00154
00155 function timePerCall() {
00156 return @( $this->time / $this->count );
00157 }
00158
00159 function memoryPerCall() {
00160 return @( $this->memory / $this->count );
00161 }
00162
00163 function callsPerRequest() {
00164 global $totalcount;
00165 return @( $this->count / $totalcount );
00166 }
00167
00168 function timePerRequest() {
00169 global $totalcount;
00170 return @( $this->time / $totalcount );
00171 }
00172
00173 function memoryPerRequest() {
00174 global $totalcount;
00175 return @( $this->memory / $totalcount );
00176 }
00177
00178 function fmttime() {
00179 return sprintf( "%5.02f", $this->time );
00180 }
00181 };
00182
00183 function compare_point( $a, $b ) {
00184 global $sort;
00185 switch ( $sort ) {
00186 case "name":
00187 return strcmp( $a->name(), $b->name() );
00188 case "time":
00189 return $a->time() > $b->time() ? -1 : 1;
00190 case "memory":
00191 return $a->memory() > $b->memory() ? -1 : 1;
00192 case "count":
00193 return $a->count() > $b->count() ? -1 : 1;
00194 case "time_per_call":
00195 return $a->timePerCall() > $b->timePerCall() ? -1 : 1;
00196 case "memory_per_call":
00197 return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1;
00198 case "calls_per_req":
00199 return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1;
00200 case "time_per_req":
00201 return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1;
00202 case "memory_per_req":
00203 return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1;
00204 }
00205 }
00206
00207 $sorts = array( 'time', 'memory', 'count', 'calls_per_req', 'name',
00208 'time_per_call', 'memory_per_call', 'time_per_req', 'memory_per_req' );
00209 $sort = 'time';
00210 if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) )
00211 $sort = $_REQUEST['sort'];
00212
00213
00214 $dbr = wfGetDB( DB_SLAVE );
00215 $res = $dbr->select( 'profiling', '*', array(), 'profileinfo.php', array( 'ORDER BY' => 'pf_name ASC' ) );
00216
00217 if (isset( $_REQUEST['filter'] ) )
00218 $filter = $_REQUEST['filter'];
00219 else
00220 $filter = '';
00221
00222 ?>
00223 <form method="get" action="profileinfo.php">
00224 <p>
00225 <input type="text" name="filter" value="<?php echo htmlspecialchars($filter)?>"/>
00226 <input type="hidden" name="sort" value="<?php echo htmlspecialchars($sort)?>"/>
00227 <input type="hidden" name="expand" value="<?php echo htmlspecialchars(implode(",", array_keys($expand)))?>"/>
00228 <input type="submit" value="Filter" />
00229 </p>
00230 </form>
00231
00232 <table cellspacing="0" border="1">
00233 <tr id="top">
00234 <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ) ?>">Name</a></th>
00235 <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ) ?>">Time (%)</a></th>
00236 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ) ?>">Memory (%)</a></th>
00237 <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ) ?>">Count</a></th>
00238 <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ) ?>">Calls/req</a></th>
00239 <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ) ?>">ms/call</a></th>
00240 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ) ?>">kb/call</a></th>
00241 <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ) ?>">ms/req</a></th>
00242 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ) ?>">kb/req</a></th>
00243 </tr>
00244 <?php
00245 $totaltime = 0.0;
00246 $totalcount = 0;
00247 $totalmemory = 0.0;
00248
00249 function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
00250 global $filter, $sort, $expand;
00251
00252 if ( $_expand === false )
00253 $_expand = $expand;
00254
00255 return htmlspecialchars(
00256 '?' .
00257 wfArrayToCGI( array(
00258 'filter' => $_filter ? $_filter : $filter,
00259 'sort' => $_sort ? $_sort : $sort,
00260 'expand' => implode( ',', array_keys( $_expand ) )
00261 ) )
00262 );
00263 }
00264
00265 $points = array();
00266 $queries = array();
00267 $sqltotal = 0.0;
00268
00269 $last = false;
00270 foreach( $res as $o ) {
00271 $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory );
00272 if( $next->name() == '-total' ) {
00273 $totaltime = $next->time();
00274 $totalcount = $next->count();
00275 $totalmemory = $next->memory();
00276 }
00277 if ( $last !== false ) {
00278 if ( preg_match( "/^".preg_quote( $last->name(), "/" )."/", $next->name() ) ) {
00279 $last->add_child($next);
00280 continue;
00281 }
00282 }
00283 $last = $next;
00284 if ( preg_match( "/^query: /", $next->name() ) || preg_match( "/^query-m: /", $next->name() ) ) {
00285 $sqltotal += $next->time();
00286 $queries[] = $next;
00287 } else {
00288 $points[] = $next;
00289 }
00290 }
00291
00292 $s = new profile_point( "SQL Queries", 0, $sqltotal, 0, 0 );
00293 foreach ( $queries as $q )
00294 $s->add_child($q);
00295 $points[] = $s;
00296
00297 usort( $points, "compare_point" );
00298
00299 foreach ( $points as $point ) {
00300 if ( strlen( $filter ) && !strstr( $point->name(), $filter ) )
00301 continue;
00302
00303 $point->display();
00304 }
00305 ?>
00306 </table>
00307
00308 <p>Total time: <tt><?php printf("%5.02f", $totaltime) ?></tt></p>
00309 <p>Total memory: <tt><?php printf("%5.02f", $totalmemory / 1024 ) ?></tt></p>
00310 </body>
00311 </html>