MediaWiki
REL1_20
|
00001 <?php 00028 ini_set( 'zlib.output_compression', 'off' ); 00029 00030 $wgEnableProfileInfo = $wgProfileToDatabase = false; 00031 if ( isset( $_SERVER['MW_COMPILED'] ) ) { 00032 require ( 'core/includes/WebStart.php' ); 00033 } else { 00034 require ( __DIR__ . '/includes/WebStart.php' ); 00035 } 00036 00037 00038 header( 'Content-Type: text/html; charset=utf-8' ); 00039 00040 ?> 00041 <html> 00042 <head> 00043 <title>Profiling data</title> 00044 <style type="text/css"> 00045 th { 00046 text-align: left; 00047 border-bottom: solid 1px black; 00048 } 00049 00050 th, td { 00051 padding-left: 0.5em; 00052 padding-right: 0.5em; 00053 } 00054 00055 td.timep, td.memoryp, td.count, td.cpr, td.tpc, td.mpc, td.tpr, td.mpr { 00056 text-align: right; 00057 } 00058 td.timep, td.tpc, td.tpr { 00059 background-color: #ffff80; 00060 } 00061 td.memoryp, td.mpc, td.mpr { 00062 background-color: #80f8ff; 00063 } 00064 td.count, td,cpr { 00065 background-color: #80ff80; 00066 } 00067 td.name { 00068 background-color: #89f9f9; 00069 } 00070 00071 tr:hover { 00072 font-weight: bold; 00073 } 00074 </style> 00075 </head> 00076 <body> 00077 <?php 00078 00079 if ( !$wgEnableProfileInfo ) { 00080 echo "<p>Disabled</p>\n"; 00081 echo "</body></html>"; 00082 exit( 1 ); 00083 } 00084 00085 $dbr = wfGetDB( DB_SLAVE ); 00086 00087 if( !$dbr->tableExists( 'profiling' ) ) { 00088 echo "<p>No 'profiling' table exists, so we can't show you anything.</p>\n"; 00089 echo "<p>If you want to log profiling data, create the table using " 00090 . "<tt>maintenance/archives/patch-profiling.sql</tt> and enable " 00091 . "<tt>\$wgProfileToDatabase</tt>.</p>\n"; 00092 echo "</body></html>"; 00093 exit( 1 ); 00094 } 00095 00096 $expand = array(); 00097 if ( isset( $_REQUEST['expand'] ) ) 00098 foreach( explode( ',', $_REQUEST['expand'] ) as $f ) 00099 $expand[$f] = true; 00100 00101 class profile_point { 00102 var $name; 00103 var $count; 00104 var $time; 00105 var $children; 00106 00107 static $totaltime, $totalmemory, $totalcount; 00108 00109 function __construct( $name, $count, $time, $memory ) { 00110 $this->name = $name; 00111 $this->count = $count; 00112 $this->time = $time; 00113 $this->memory = $memory; 00114 $this->children = array(); 00115 } 00116 00117 function add_child( $child ) { 00118 $this->children[] = $child; 00119 } 00120 00121 function display( $expand, $indent = 0.0 ) { 00122 usort( $this->children, 'compare_point' ); 00123 00124 $ex = isset( $expand[$this->name()] ); 00125 00126 if ( !$ex ) { 00127 if ( count( $this->children ) ) { 00128 $url = getEscapedProfileUrl( false, false, $expand + array( $this->name() => true ) ); 00129 $extet = " <a href=\"$url\">[+]</a>"; 00130 } else { 00131 $extet = ''; 00132 } 00133 } else { 00134 $e = array(); 00135 foreach ( $expand as $name => $ep ) { 00136 if ( $name != $this->name() ) { 00137 $e += array( $name => $ep ); 00138 } 00139 } 00140 00141 $extet = " <a href=\"" . getEscapedProfileUrl( false, false, $e ) . "\">[–]</a>"; 00142 } 00143 ?> 00144 <tr> 00145 <td class="name" style="padding-left: <?php echo $indent ?>em;"> 00146 <?php echo htmlspecialchars( $this->name() ) . $extet ?> 00147 </td> 00148 <td class="timep"><?php echo @wfPercent( $this->time() / self::$totaltime * 100 ) ?></td> 00149 <td class="memoryp"><?php echo @wfPercent( $this->memory() / self::$totalmemory * 100 ) ?></td> 00150 <td class="count"><?php echo $this->count() ?></td> 00151 <td class="cpr"><?php echo round( sprintf( '%.2f', $this->callsPerRequest() ), 2 ) ?></td> 00152 <td class="tpc"><?php echo round( sprintf( '%.2f', $this->timePerCall() ), 2 ) ?></td> 00153 <td class="mpc"><?php echo round( sprintf( '%.2f' ,$this->memoryPerCall() / 1024 ), 2 ) ?></td> 00154 <td class="tpr"><?php echo @round( sprintf( '%.2f', $this->time() / self::$totalcount ), 2 ) ?></td> 00155 <td class="mpr"><?php echo @round( sprintf( '%.2f' ,$this->memory() / self::$totalcount / 1024 ), 2 ) ?></td> 00156 </tr> 00157 <?php 00158 if ( $ex ) { 00159 foreach ( $this->children as $child ) { 00160 $child->display( $expand, $indent + 2 ); 00161 } 00162 } 00163 } 00164 00165 function name() { 00166 return $this->name; 00167 } 00168 00169 function count() { 00170 return $this->count; 00171 } 00172 00173 function time() { 00174 return $this->time; 00175 } 00176 00177 function memory() { 00178 return $this->memory; 00179 } 00180 00181 function timePerCall() { 00182 return @( $this->time / $this->count ); 00183 } 00184 00185 function memoryPerCall() { 00186 return @( $this->memory / $this->count ); 00187 } 00188 00189 function callsPerRequest() { 00190 return @( $this->count / self::$totalcount ); 00191 } 00192 00193 function timePerRequest() { 00194 return @( $this->time / self::$totalcount ); 00195 } 00196 00197 function memoryPerRequest() { 00198 return @( $this->memory / self::$totalcount ); 00199 } 00200 00201 function fmttime() { 00202 return sprintf( "%5.02f", $this->time ); 00203 } 00204 }; 00205 00206 function compare_point(profile_point $a, profile_point $b) { 00207 global $sort; 00208 switch ( $sort ) { 00209 case "name": 00210 return strcmp( $a->name(), $b->name() ); 00211 case "time": 00212 return $a->time() > $b->time() ? -1 : 1; 00213 case "memory": 00214 return $a->memory() > $b->memory() ? -1 : 1; 00215 case "count": 00216 return $a->count() > $b->count() ? -1 : 1; 00217 case "time_per_call": 00218 return $a->timePerCall() > $b->timePerCall() ? -1 : 1; 00219 case "memory_per_call": 00220 return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1; 00221 case "calls_per_req": 00222 return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1; 00223 case "time_per_req": 00224 return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1; 00225 case "memory_per_req": 00226 return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1; 00227 } 00228 } 00229 00230 $sorts = array( 'time', 'memory', 'count', 'calls_per_req', 'name', 00231 'time_per_call', 'memory_per_call', 'time_per_req', 'memory_per_req' ); 00232 $sort = 'time'; 00233 if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) ) 00234 $sort = $_REQUEST['sort']; 00235 00236 $res = $dbr->select( 'profiling', '*', array(), 'profileinfo.php', array( 'ORDER BY' => 'pf_name ASC' ) ); 00237 00238 if (isset( $_REQUEST['filter'] ) ) 00239 $filter = $_REQUEST['filter']; 00240 else 00241 $filter = ''; 00242 00243 ?> 00244 <form method="get" action="profileinfo.php"> 00245 <p> 00246 <input type="text" name="filter" value="<?php echo htmlspecialchars($filter)?>"/> 00247 <input type="hidden" name="sort" value="<?php echo htmlspecialchars($sort)?>"/> 00248 <input type="hidden" name="expand" value="<?php echo htmlspecialchars(implode(",", array_keys($expand)))?>"/> 00249 <input type="submit" value="Filter" /> 00250 </p> 00251 </form> 00252 00253 <table cellspacing="0" border="1"> 00254 <tr id="top"> 00255 <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ) ?>">Name</a></th> 00256 <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ) ?>">Time (%)</a></th> 00257 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ) ?>">Memory (%)</a></th> 00258 <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ) ?>">Count</a></th> 00259 <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ) ?>">Calls/req</a></th> 00260 <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ) ?>">ms/call</a></th> 00261 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ) ?>">kb/call</a></th> 00262 <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ) ?>">ms/req</a></th> 00263 <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ) ?>">kb/req</a></th> 00264 </tr> 00265 <?php 00266 profile_point::$totaltime = 0.0; 00267 profile_point::$totalcount = 0; 00268 profile_point::$totalmemory = 0.0; 00269 00270 function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) { 00271 global $filter, $sort, $expand; 00272 00273 if ( $_expand === false ) 00274 $_expand = $expand; 00275 00276 return htmlspecialchars( 00277 '?' . 00278 wfArrayToCGI( array( 00279 'filter' => $_filter ? $_filter : $filter, 00280 'sort' => $_sort ? $_sort : $sort, 00281 'expand' => implode( ',', array_keys( $_expand ) ) 00282 ) ) 00283 ); 00284 } 00285 00286 $points = array(); 00287 $queries = array(); 00288 $sqltotal = 0.0; 00289 00290 $last = false; 00291 foreach( $res as $o ) { 00292 $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory ); 00293 if( $next->name() == '-total' ) { 00294 profile_point::$totaltime = $next->time(); 00295 profile_point::$totalcount = $next->count(); 00296 profile_point::$totalmemory = $next->memory(); 00297 } 00298 if ( $last !== false ) { 00299 if ( preg_match( "/^".preg_quote( $last->name(), "/" )."/", $next->name() ) ) { 00300 $last->add_child($next); 00301 continue; 00302 } 00303 } 00304 $last = $next; 00305 if ( preg_match( "/^query: /", $next->name() ) || preg_match( "/^query-m: /", $next->name() ) ) { 00306 $sqltotal += $next->time(); 00307 $queries[] = $next; 00308 } else { 00309 $points[] = $next; 00310 } 00311 } 00312 00313 $s = new profile_point( "SQL Queries", 0, $sqltotal, 0, 0 ); 00314 foreach ( $queries as $q ) 00315 $s->add_child($q); 00316 $points[] = $s; 00317 00318 usort( $points, "compare_point" ); 00319 00320 foreach ( $points as $point ) { 00321 if ( strlen( $filter ) && !strstr( $point->name(), $filter ) ) 00322 continue; 00323 00324 $point->display( $expand ); 00325 } 00326 ?> 00327 </table> 00328 00329 <p>Total time: <tt><?php printf("%5.02f", profile_point::$totaltime) ?></tt></p> 00330 <p>Total memory: <tt><?php printf("%5.02f", profile_point::$totalmemory / 1024 ) ?></tt></p> 00331 </body> 00332 </html>