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