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