[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/ -> profileinfo.php (source)

   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  
  28  ini_set( 'zlib.output_compression', 'off' );
  29  
  30  $wgEnableProfileInfo = $wgProfileToDatabase = false;
  31  require  __DIR__ . '/includes/WebStart.php';
  32  
  33  header( 'Content-Type: text/html; charset=utf-8' );
  34  
  35  ?>
  36  <!DOCTYPE html>
  37  <html>
  38  <head>
  39      <meta charset="UTF-8">
  40      <title>Profiling data</title>
  41      <style>
  42          /* noc.wikimedia.org/base.css */
  43  
  44          * {
  45              margin: 0;
  46              padding: 0;
  47          }
  48  
  49          body {
  50              padding: 0.5em 1em;
  51              background: #fff;
  52              font: 14px/1.6 sans-serif;
  53              color: #333;
  54          }
  55  
  56          p, ul, ol, table {
  57              margin: 0.5em 0;
  58          }
  59  
  60          a {
  61              color: #0645AD;
  62              text-decoration: none;
  63          }
  64  
  65          a:hover {
  66              text-decoration: underline;
  67          }
  68  
  69          /*!
  70           * Bootstrap v2.1.1
  71           *
  72           * Copyright 2012 Twitter, Inc
  73           * Licensed under the Apache License v2.0
  74           * http://www.apache.org/licenses/LICENSE-2.0
  75           *
  76           * Designed and built with all the love in the world @twitter by @mdo and @fat.
  77           */
  78  
  79          table {
  80              max-width: 100%;
  81              background-color: transparent;
  82              border-collapse: collapse;
  83              border-spacing: 0;
  84          }
  85  
  86          .table {
  87              width: 100%;
  88              margin-bottom: 20px;
  89          }
  90  
  91          .table th,
  92          .table td {
  93              padding: 0.1em;
  94              text-align: left;
  95              vertical-align: top;
  96              border-top: 1px solid #ddd;
  97          }
  98  
  99          .table th {
 100              font-weight: bold;
 101          }
 102  
 103          .table thead th {
 104              vertical-align: bottom;
 105          }
 106  
 107          .table thead:first-child tr:first-child th,
 108          .table thead:first-child tr:first-child td {
 109              border-top: 0;
 110          }
 111  
 112          .table tbody + tbody {
 113              border-top: 2px solid #ddd;
 114          }
 115  
 116          .table-condensed th,
 117          .table-condensed td {
 118              padding: 4px 5px;
 119          }
 120  
 121          .table-striped tbody tr:nth-child(odd) td,
 122          .table-striped tbody tr:nth-child(odd) th {
 123              background-color: #f9f9f9;
 124          }
 125  
 126          .table-hover tbody tr:hover td,
 127          .table-hover tbody tr:hover th {
 128              background-color: #f5f5f5;
 129          }
 130  
 131          hr {
 132              margin: 20px 0;
 133              border: 0;
 134              border-top: 1px solid #eee;
 135              border-bottom: 1px solid #fff;
 136          }
 137      </style>
 138  </head>
 139  <body>
 140  <?php
 141  
 142  if ( !$wgEnableProfileInfo ) {
 143      echo '<p>Disabled</p>'
 144          . '</body></html>';
 145      exit( 1 );
 146  }
 147  
 148  $dbr = wfGetDB( DB_SLAVE );
 149  
 150  if ( !$dbr->tableExists( 'profiling' ) ) {
 151      echo '<p>No <code>profiling</code> table exists, so we can\'t show you anything.</p>'
 152          . '<p>If you want to log profiling data, enable <code>$wgProfileToDatabase</code>'
 153          . ' in your LocalSettings.php and run <code>maintenance/update.php</code> to'
 154          . ' create the profiling table.'
 155          . '</body></html>';
 156      exit( 1 );
 157  }
 158  
 159  $expand = array();
 160  if ( isset( $_REQUEST['expand'] ) ) {
 161      foreach ( explode( ',', $_REQUEST['expand'] ) as $f ) {
 162          $expand[$f] = true;
 163      }
 164  }
 165  
 166  // @codingStandardsIgnoreStart
 167  class profile_point {
 168      // @codingStandardsIgnoreEnd
 169  
 170      public $name;
 171      public $count;
 172      public $time;
 173      public $children;
 174  
 175      public static $totaltime, $totalmemory, $totalcount;
 176  
 177  	public function __construct( $name, $count, $time, $memory ) {
 178          $this->name = $name;
 179          $this->count = $count;
 180          $this->time = $time;
 181          $this->memory = $memory;
 182          $this->children = array();
 183      }
 184  
 185  	public function add_child( $child ) {
 186          $this->children[] = $child;
 187      }
 188  
 189  	public function display( $expand, $indent = 0.0 ) {
 190          usort( $this->children, 'compare_point' );
 191  
 192          $ex = isset( $expand[$this->name()] );
 193  
 194          $anchor = str_replace( '"', '', $this->name() );
 195  
 196          if ( !$ex ) {
 197              if ( count( $this->children ) ) {
 198                  $url = getEscapedProfileUrl( false, false, $expand + array( $this->name() => true ) );
 199                  $extet = " <a id=\"{$anchor}\" href=\"{$url}#{$anchor}\">[+]</a>";
 200              } else {
 201                  $extet = '';
 202              }
 203          } else {
 204              $e = array();
 205              foreach ( $expand as $name => $ep ) {
 206                  if ( $name != $this->name() ) {
 207                      $e += array( $name => $ep );
 208                  }
 209              }
 210              $url = getEscapedProfileUrl( false, false, $e );
 211              $extet = " <a id=\"{$anchor}\" href=\"{$url}#{$anchor}\">[–]</a>";
 212          }
 213          ?>
 214      <tr>
 215          <th>
 216              <div style="margin-left: <?php echo (int)$indent; ?>em;">
 217                  <?php echo htmlspecialchars( str_replace( ',', ', ', $this->name() ) ) . $extet ?>
 218              </div>
 219          </th>
 220          <?php //@codingStandardsIgnoreStart ?>
 221          <td class="mw-profileinfo-timep"><?php echo @wfPercent( $this->time() / self::$totaltime * 100 ); ?></td>
 222          <td class="mw-profileinfo-memoryp"><?php echo @wfPercent( $this->memory() / self::$totalmemory * 100 ); ?></td>
 223          <td class="mw-profileinfo-count"><?php echo $this->count(); ?></td>
 224          <td class="mw-profileinfo-cpr"><?php echo round( sprintf( '%.2f', $this->callsPerRequest() ), 2 ); ?></td>
 225          <td class="mw-profileinfo-tpc"><?php echo round( sprintf( '%.2f', $this->timePerCall() ), 2 ); ?></td>
 226          <td class="mw-profileinfo-mpc"><?php echo round( sprintf( '%.2f', $this->memoryPerCall() / 1024 ), 2 ); ?></td>
 227          <td class="mw-profileinfo-tpr"><?php echo @round( sprintf( '%.2f', $this->time() / self::$totalcount ), 2 ); ?></td>
 228          <td class="mw-profileinfo-mpr"><?php echo @round( sprintf( '%.2f', $this->memory() / self::$totalcount / 1024 ), 2 ); ?></td>
 229          <?php //@codingStandardsIgnoreEnd ?>
 230      </tr>
 231          <?php
 232          if ( $ex ) {
 233              foreach ( $this->children as $child ) {
 234                  $child->display( $expand, $indent + 2 );
 235              }
 236          }
 237      }
 238  
 239  	public function name() {
 240          return $this->name;
 241      }
 242  
 243  	public function count() {
 244          return $this->count;
 245      }
 246  
 247  	public function time() {
 248          return $this->time;
 249      }
 250  
 251  	public function memory() {
 252          return $this->memory;
 253      }
 254  
 255  	public function timePerCall() {
 256          // @codingStandardsIgnoreStart
 257          return @( $this->time / $this->count );
 258          // @codingStandardsIgnoreEnd
 259      }
 260  
 261  	public function memoryPerCall() {
 262          // @codingStandardsIgnoreStart
 263          return @( $this->memory / $this->count );
 264          // @codingStandardsIgnoreEnd
 265      }
 266  
 267  	public function callsPerRequest() {
 268          // @codingStandardsIgnoreStart
 269          return @( $this->count / self::$totalcount );
 270          // @codingStandardsIgnoreEnd
 271      }
 272  
 273  	public function timePerRequest() {
 274          // @codingStandardsIgnoreStart
 275          return @( $this->time / self::$totalcount );
 276          // @codingStandardsIgnoreEnd
 277      }
 278  
 279  	public function memoryPerRequest() {
 280          // @codingStandardsIgnoreStart
 281          return @( $this->memory / self::$totalcount );
 282          // @codingStandardsIgnoreEnd
 283      }
 284  
 285  	public function fmttime() {
 286          return sprintf( '%5.02f', $this->time );
 287      }
 288  };
 289  
 290  function compare_point( profile_point $a, profile_point $b ) {
 291      // @codingStandardsIgnoreStart
 292      global $sort;
 293      // @codingStandardsIgnoreEnd
 294      switch ( $sort ) {
 295          case 'name':
 296              return strcmp( $a->name(), $b->name() );
 297          case 'time':
 298              return $a->time() > $b->time() ? -1 : 1;
 299          case 'memory':
 300              return $a->memory() > $b->memory() ? -1 : 1;
 301          case 'count':
 302              return $a->count() > $b->count() ? -1 : 1;
 303          case 'time_per_call':
 304              return $a->timePerCall() > $b->timePerCall() ? -1 : 1;
 305          case 'memory_per_call':
 306              return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1;
 307          case 'calls_per_req':
 308              return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1;
 309          case 'time_per_req':
 310              return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1;
 311          case 'memory_per_req':
 312              return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1;
 313      }
 314  }
 315  
 316  $sorts = array( 'time', 'memory', 'count', 'calls_per_req', 'name',
 317      'time_per_call', 'memory_per_call', 'time_per_req', 'memory_per_req' );
 318  $sort = 'time';
 319  if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) ) {
 320      $sort = $_REQUEST['sort'];
 321  }
 322  
 323  $res = $dbr->select( 'profiling', '*', array(), 'profileinfo.php', array( 'ORDER BY' => 'pf_name ASC' ) );
 324  
 325  if ( isset( $_REQUEST['filter'] ) ) {
 326      $filter = $_REQUEST['filter'];
 327  } else {
 328      $filter = '';
 329  }
 330  
 331  ?>
 332  <form method="get" action="profileinfo.php">
 333      <p>
 334          <input type="text" name="filter" value="<?php echo htmlspecialchars( $filter ); ?>">
 335          <input type="hidden" name="sort" value="<?php echo htmlspecialchars( $sort ); ?>">
 336          <input type="hidden" name="expand" value="<?php echo htmlspecialchars( implode( ",", array_keys( $expand ) ) ); ?>">
 337          <input type="submit" value="Filter">
 338      </p>
 339  </form>
 340  
 341  <table class="mw-profileinfo-table table table-striped table-hover">
 342      <thead>
 343      <tr>
 344          <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ); ?>">Name</a></th>
 345          <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ); ?>">Time (%)</a></th>
 346          <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ); ?>">Memory (%)</a></th>
 347          <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ); ?>">Count</a></th>
 348          <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ); ?>">Calls/req</a></th>
 349          <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ); ?>">ms/call</a></th>
 350          <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ); ?>">kb/call</a></th>
 351          <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ); ?>">ms/req</a></th>
 352          <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ); ?>">kb/req</a></th>
 353      </tr>
 354      </thead>
 355      <tbody>
 356      <?php
 357      profile_point::$totaltime = 0.0;
 358      profile_point::$totalcount = 0;
 359      profile_point::$totalmemory = 0.0;
 360  
 361  	function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
 362          // @codingStandardsIgnoreStart
 363          global $filter, $sort, $expand;
 364          // @codingStandardsIgnoreEnd
 365  
 366          if ( $_expand === false ) {
 367              $_expand = $expand;
 368          }
 369  
 370          return htmlspecialchars(
 371              '?' .
 372                  wfArrayToCgi( array(
 373                      'filter' => $_filter ? $_filter : $filter,
 374                      'sort' => $_sort ? $_sort : $sort,
 375                      'expand' => implode( ',', array_keys( $_expand ) )
 376                  ) )
 377          );
 378      }
 379  
 380      $points = array();
 381      $queries = array();
 382      $sqltotal = 0.0;
 383  
 384      $last = false;
 385      foreach ( $res as $o ) {
 386          $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory );
 387          if ( $next->name() == '-total' ) {
 388              profile_point::$totaltime = $next->time();
 389              profile_point::$totalcount = $next->count();
 390              profile_point::$totalmemory = $next->memory();
 391          }
 392          if ( $last !== false ) {
 393              if ( preg_match( '/^' . preg_quote( $last->name(), '/' ) . '/', $next->name() ) ) {
 394                  $last->add_child( $next );
 395                  continue;
 396              }
 397          }
 398          $last = $next;
 399          if ( preg_match( '/^query: /', $next->name() ) || preg_match( '/^query-m: /', $next->name() ) ) {
 400              $sqltotal += $next->time();
 401              $queries[] = $next;
 402          } else {
 403              $points[] = $next;
 404          }
 405      }
 406  
 407      $s = new profile_point( 'SQL Queries', 0, $sqltotal, 0, 0 );
 408      foreach ( $queries as $q ) {
 409          $s->add_child( $q );
 410      }
 411      $points[] = $s;
 412  
 413      usort( $points, 'compare_point' );
 414  
 415      foreach ( $points as $point ) {
 416          if ( strlen( $filter ) && !strstr( $point->name(), $filter ) ) {
 417              continue;
 418          }
 419  
 420          $point->display( $expand );
 421      }
 422      ?>
 423      </tbody>
 424  </table>
 425  <hr>
 426  <p>Total time: <code><?php printf( '%5.02f', profile_point::$totaltime ); ?></code></p>
 427  
 428  <p>Total memory: <code><?php printf( '%5.02f', profile_point::$totalmemory / 1024 ); ?></code></p>
 429  <hr />
 430  </body>
 431  </html>


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1