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>