Chad has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/173348

Change subject: Refactor profiling output from profiling
......................................................................

Refactor profiling output from profiling

Change-Id: I266ed82031a434465f64896eb327f3872fdf1db1
---
M autoload.php
M includes/profiler/Profiler.php
M includes/profiler/ProfilerStandard.php
M includes/profiler/ProfilerStub.php
M includes/profiler/ProfilerXhprof.php
A includes/profiler/output/ProfilerOutput.php
R includes/profiler/output/ProfilerOutputDb.php
R includes/profiler/output/ProfilerOutputText.php
R includes/profiler/output/ProfilerOutputUdp.php
M maintenance/Maintenance.php
10 files changed, 157 insertions(+), 93 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/48/173348/1

diff --git a/autoload.php b/autoload.php
index c5fc22c..ded17bb 100644
--- a/autoload.php
+++ b/autoload.php
@@ -880,10 +880,11 @@
        'ProcessCacheLRU' => __DIR__ . '/includes/libs/ProcessCacheLRU.php',
        'ProfileSection' => __DIR__ . '/includes/profiler/ProfileSection.php',
        'Profiler' => __DIR__ . '/includes/profiler/Profiler.php',
-       'ProfilerSimpleDB' => __DIR__ . 
'/includes/profiler/ProfilerSimpleDB.php',
-       'ProfilerSimpleText' => __DIR__ . 
'/includes/profiler/ProfilerSimpleText.php',
+       'ProfilerOutput' => __DIR__ . 
'/includes/profiler/output/ProfilerOutput.php',
+       'ProfilerOutputDb' => __DIR__ . 
'/includes/profiler/output/ProfilerOutputDb.php',
+       'ProfilerOutputText' => __DIR__ . 
'/includes/profiler/output/ProfilerOutputText.php',
+       'ProfilerOutputUdp' => __DIR__ . 
'/includes/profiler/output/ProfilerOutputUdp.php',
        'ProfilerSimpleTrace' => __DIR__ . 
'/includes/profiler/ProfilerSimpleTrace.php',
-       'ProfilerSimpleUDP' => __DIR__ . 
'/includes/profiler/ProfilerSimpleUDP.php',
        'ProfilerStandard' => __DIR__ . 
'/includes/profiler/ProfilerStandard.php',
        'ProfilerStub' => __DIR__ . '/includes/profiler/ProfilerStub.php',
        'ProfilerXhprof' => __DIR__ . '/includes/profiler/ProfilerXhprof.php',
@@ -1315,4 +1316,4 @@
        'lessc_formatter_lessjs' => __DIR__ . '/includes/libs/lessc.inc.php',
        'lessc_parser' => __DIR__ . '/includes/libs/lessc.inc.php',
        'profile_point' => __DIR__ . '/profileinfo.php',
-);
+);
\ No newline at end of file
diff --git a/includes/profiler/Profiler.php b/includes/profiler/Profiler.php
index 078b66b..d59fd64 100644
--- a/includes/profiler/Profiler.php
+++ b/includes/profiler/Profiler.php
@@ -33,6 +33,8 @@
        protected $profileID = false;
        /** @var bool Whether MediaWiki is in a SkinTemplate output context */
        protected $templated = false;
+       /** @var array All of the params passed from $wgProfiler */
+       protected $params = array();
 
        /** @var TransactionProfiler */
        protected $trxProfiler;
@@ -49,6 +51,7 @@
                if ( isset( $params['profileID'] ) ) {
                        $this->profileID = $params['profileID'];
                }
+               $this->params = $params;
                $this->trxProfiler = new TransactionProfiler();
        }
 
@@ -128,7 +131,33 @@
        /**
         * Log the data to some store or even the page output
         */
-       abstract public function logData();
+       public function logData() {
+               $output = isset( $this->params['output'] ) ?
+                       $this->params['output'] : null;
+               if ( !$output ) {
+                       // return early when no output class defined
+                       return;
+               }
+               $class = 'ProfilerOutput' . ucfirst( strtolower( $output ) );
+               $output = new $class( $this, $this->params );
+               if ( $output->canUse() ) {
+                       $output->log();
+               }
+       }
+
+       /**
+        * Get the content type sent out to the client.
+        * Used for profilers that output instead of store data.
+        * @return string
+        */
+       public function getContentType() {
+               foreach ( headers_list() as $header ) {
+                       if ( preg_match( '#^content-type: (\w+/\w+);?#i', 
$header, $m ) ) {
+                               return $m[1];
+                       }
+               }
+               return null;
+       }
 
        /**
         * Mark this call as templated or not
@@ -139,6 +168,15 @@
                $this->templated = $t;
        }
 
+               /**
+        * Was this call as templated or not
+        *
+        * @return bool
+        */
+       public function getTemplated() {
+               return $this->templated;
+       }
+
        /**
         * Returns a profiling output to be stored in debug file
         *
diff --git a/includes/profiler/ProfilerStandard.php 
b/includes/profiler/ProfilerStandard.php
index b873806..345fef8 100644
--- a/includes/profiler/ProfilerStandard.php
+++ b/includes/profiler/ProfilerStandard.php
@@ -237,13 +237,6 @@
        }
 
        /**
-        * Log the data to some store or even the page output
-        */
-       public function logData() {
-               /* Implement in subclasses */
-       }
-
-       /**
         * Returns a profiling output to be stored in debug file
         *
         * @return string
@@ -328,6 +321,17 @@
                # which has been fixed in recent releases.
                return sprintf( "%10s %s %s\n",
                        trim( sprintf( "%7.3f", $delta * 1000.0 ) ), $space, 
$fname );
+       }
+
+       /**
+        * Return the collated data, collating first if need be
+        * @return array
+        */
+       public function getCollatedData() {
+               if ( !$this->collateDone ) {
+                       $this->collateData();
+               }
+               return $this->collated;
        }
 
        /**
@@ -519,20 +523,6 @@
                        $count ++;
                }
                return $count;
-       }
-
-       /**
-        * Get the content type sent out to the client.
-        * Used for profilers that output instead of store data.
-        * @return string
-        */
-       protected function getContentType() {
-               foreach ( headers_list() as $header ) {
-                       if ( preg_match( '#^content-type: (\w+/\w+);?#i', 
$header, $m ) ) {
-                               return $m[1];
-                       }
-               }
-               return null;
        }
 
        /**
diff --git a/includes/profiler/ProfilerStub.php 
b/includes/profiler/ProfilerStub.php
index 43e2193..c9b91de 100644
--- a/includes/profiler/ProfilerStub.php
+++ b/includes/profiler/ProfilerStub.php
@@ -43,9 +43,6 @@
        public function close() {
        }
 
-       public function logData() {
-       }
-
        public function getCurrentSection() {
                return '';
        }
diff --git a/includes/profiler/ProfilerXhprof.php 
b/includes/profiler/ProfilerXhprof.php
index 1e83e27..852370d 100644
--- a/includes/profiler/ProfilerXhprof.php
+++ b/includes/profiler/ProfilerXhprof.php
@@ -335,19 +335,6 @@
        }
 
        /**
-        * Get the content type of the current request.
-        * @return string
-        */
-       protected function getContentType() {
-               foreach ( headers_list() as $header ) {
-                       if ( preg_match( '#^content-type: (\w+/\w+);?#i', 
$header, $m ) ) {
-                               return $m[1];
-                       }
-               }
-               return 'application/octet-stream';
-       }
-
-       /**
         * Returns a profiling output to be stored in debug file
         *
         * @return string
diff --git a/includes/profiler/output/ProfilerOutput.php 
b/includes/profiler/output/ProfilerOutput.php
new file mode 100644
index 0000000..410d0e1
--- /dev/null
+++ b/includes/profiler/output/ProfilerOutput.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Base class for profiling output
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Profiler
+ */
+
+abstract class ProfilerOutput {
+       /** @var Profiler */
+       protected $collector;
+       /** @var array Configuration of $wgProfiler */
+       protected $params = array();
+
+       /**
+        * Constructor
+        * @param Profiler $collector The actual profiler
+        * @param array $params Configuration array, passed down from 
$wgProfiler
+        */
+       public function __construct( Profiler $collector, array $params ) {
+               $this->collector = $collector;
+               $this->params = $params;
+       }
+
+       /**
+        * Can this output type be used?
+        * @return bool
+        */
+       public function canUse() {
+               return true;
+       }
+
+       /**
+        * Delegate to the proper method
+        */
+       public function log() {
+               switch( get_class( $this->collector ) ) {
+                       case 'ProfilerStandard':
+                               $this->logStandardData( 
$this->collector->getCollatedData() );
+                               break;
+                       case 'ProfilerXhprof':
+                               $this->logXhprofData();
+                               break;
+               }
+       }
+
+       /**
+        * Log MediaWiki-style profiling data.
+        * Up to classes to implement this.
+        * @param array $collated The collated MediaWiki profiling data
+        */
+       protected function logStandardData( array $collated ) {}
+
+       /**
+        * Log MediaWiki-style profiling data.
+        * Up to classes to implement this.
+        */
+       protected function logXhprofData() {}
+}
\ No newline at end of file
diff --git a/includes/profiler/ProfilerSimpleDB.php 
b/includes/profiler/output/ProfilerOutputDb.php
similarity index 91%
rename from includes/profiler/ProfilerSimpleDB.php
rename to includes/profiler/output/ProfilerOutputDb.php
index 911b926..ee13b2b 100644
--- a/includes/profiler/ProfilerSimpleDB.php
+++ b/includes/profiler/output/ProfilerOutputDb.php
@@ -26,17 +26,17 @@
  *
  * @ingroup Profiler
  */
-class ProfilerSimpleDB extends ProfilerStandard {
+class ProfilerOutputDb extends ProfilerOutput {
+       public function canUse() {
+               # Do not log anything if database is readonly (bug 5375)
+               return !wfReadOnly();
+       }
+
        /**
         * Log the whole profiling data into the database.
         */
-       public function logData() {
+       protected function logStandardData( array $collated ) {
                global $wgProfilePerHost;
-
-               # Do not log anything if database is readonly (bug 5375)
-               if ( wfReadOnly() ) {
-                       return;
-               }
 
                if ( $wgProfilePerHost ) {
                        $pfhost = wfHostname();
@@ -45,14 +45,12 @@
                }
 
                try {
-                       $this->collateData();
-
                        $dbw = wfGetDB( DB_MASTER );
                        $useTrx = ( $dbw->getType() === 'sqlite' ); // much 
faster
                        if ( $useTrx ) {
                                $dbw->startAtomic( __METHOD__ );
                        }
-                       foreach ( $this->collated as $name => $data ) {
+                       foreach ( $collated as $name => $data ) {
                                $eventCount = $data['count'];
                                $timeSum = (float)( $data['real'] * 1000 );
                                $memorySum = (float)$data['memory'];
diff --git a/includes/profiler/ProfilerSimpleText.php 
b/includes/profiler/output/ProfilerOutputText.php
similarity index 74%
rename from includes/profiler/ProfilerSimpleText.php
rename to includes/profiler/output/ProfilerOutputText.php
index 264845e..9e65745 100644
--- a/includes/profiler/ProfilerSimpleText.php
+++ b/includes/profiler/output/ProfilerOutputText.php
@@ -31,30 +31,20 @@
  *
  * @ingroup Profiler
  */
-class ProfilerSimpleText extends ProfilerStandard {
-       public $visible = false; /* Show as <PRE> or <!-- ? */
-
-       public function __construct( $profileConfig ) {
-               if ( isset( $profileConfig['visible'] ) && 
$profileConfig['visible'] ) {
-                       $this->visible = true;
-               }
-               parent::__construct( $profileConfig );
-       }
-
-       public function logData() {
+class ProfilerOutputText extends ProfilerOutput {
+       protected function logStandardData( array $collated ) {
                $out = '';
-               if ( $this->templated ) {
-                       $this->close();
-                       $totalReal = isset( $this->collated['-total'] )
-                               ? $this->collated['-total']['real']
+               if ( $this->collector->getTemplated() ) {
+                       $totalReal = isset( $collated['-total'] )
+                               ? $collated['-total']['real']
                                : 0; // profiling mismatch error?
 
-                       uasort( $this->collated, function( $a, $b ) {
+                       uasort( $collated, function( $a, $b ) {
                                // sort descending by time elapsed
                                return $a['real'] < $b['real'];
                        } );
 
-                       array_walk( $this->collated,
+                       array_walk( $collated,
                                function( $item, $key ) use ( &$out, $totalReal 
) {
                                        $perc = $totalReal ? $item['real'] / 
$totalReal * 100 : 0;
                                        $out .= sprintf( "%6.2f%% %3.6f %6d - 
%s\n",
@@ -62,11 +52,13 @@
                                }
                        );
 
-                       $contentType = $this->getContentType();
+                       $contentType = $this->collector->getContentType();
                        if ( PHP_SAPI === 'cli' ) {
                                print "<!--\n{$out}\n-->\n";
                        } elseif ( $contentType === 'text/html' ) {
-                               if ( $this->visible ) {
+                               $visible = isset( $this->params['visible'] ) ?
+                                       $this->params['visible'] : false;
+                               if ( $visible ) {
                                        print "<pre>{$out}</pre>";
                                } else {
                                        print "<!--\n{$out}\n-->\n";
diff --git a/includes/profiler/ProfilerSimpleUDP.php 
b/includes/profiler/output/ProfilerOutputUdp.php
similarity index 83%
rename from includes/profiler/ProfilerSimpleUDP.php
rename to includes/profiler/output/ProfilerOutputUdp.php
index ad16a18..d3cdcdc 100644
--- a/includes/profiler/ProfilerSimpleUDP.php
+++ b/includes/profiler/output/ProfilerOutputUdp.php
@@ -27,21 +27,19 @@
  *  http://git.wikimedia.org/tree/operations%2Fsoftware.git/master/udpprofile)
  * @ingroup Profiler
  */
-class ProfilerSimpleUDP extends ProfilerStandard {
-       public function logData() {
+class ProfilerOutputUdp extends ProfilerOutput {
+       public function canUse() {
+               # Sockets are not enabled
+               return function_exists( 'socket_create' );
+       }
+
+       protected function logStandardData( array $collated ) {
                global $wgUDPProfilerHost, $wgUDPProfilerPort, 
$wgUDPProfilerFormatString;
-
-               $this->close();
-
-               if ( !function_exists( 'socket_create' ) ) {
-                       # Sockets are not enabled
-                       return;
-               }
 
                $sock = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
                $plength = 0;
                $packet = "";
-               foreach ( $this->collated as $entry => $pfdata ) {
+               foreach ( $collated as $entry => $pfdata ) {
                        if ( !isset( $pfdata['count'] )
                                || !isset( $pfdata['cpu'] )
                                || !isset( $pfdata['cpu_sq'] )
@@ -49,7 +47,7 @@
                                || !isset( $pfdata['real_sq'] ) ) {
                                continue;
                        }
-                       $pfline = sprintf( $wgUDPProfilerFormatString, 
$this->getProfileID(), $pfdata['count'],
+                       $pfline = sprintf( $wgUDPProfilerFormatString, 
$this->collector->getProfileID(), $pfdata['count'],
                                $pfdata['cpu'], $pfdata['cpu_sq'], 
$pfdata['real'], $pfdata['real_sq'], $entry,
                                $pfdata['memory'] );
                        $length = strlen( $pfline );
diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php
index d740f56..3f8f6e8 100644
--- a/maintenance/Maintenance.php
+++ b/maintenance/Maintenance.php
@@ -446,7 +446,6 @@
                $this->addOption( 'server', "The protocol and server name to 
use in URLs, e.g. " .
                        "http://en.wikipedia.org. This is sometimes necessary 
because " .
                        "server name detection may fail in command line 
scripts.", false, true );
-               $this->addOption( 'profiler', 'Set to "text" or "trace" to show 
profiling output', false, true );
 
                # Save generic options to display them separately in help
                $this->mGenericParameters = $this->mParams;
@@ -930,16 +929,6 @@
                // @codingStandardsIgnoreStart
 
                $this->adjustMemoryLimit();
-
-               // Per-script profiling; useful for debugging
-               $forcedProfiler = $this->getOption( 'profiler' );
-               if ( $forcedProfiler === 'text' ) {
-                       Profiler::setInstance( new ProfilerSimpleText( array() 
) );
-                       Profiler::instance()->setTemplated( true );
-               } elseif ( $forcedProfiler === 'trace' ) {
-                       Profiler::setInstance( new ProfilerSimpleTrace( array() 
) );
-                       Profiler::instance()->setTemplated( true );
-               }
        }
 
        /**

-- 
To view, visit https://gerrit.wikimedia.org/r/173348
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I266ed82031a434465f64896eb327f3872fdf1db1
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Chad <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to