diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2015-06-04 07:31:04 +0200 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2015-06-04 07:58:39 +0200 |
commit | f6d65e533c62f6deb21342d4901ece24497b433e (patch) | |
tree | f28adf0362d14bcd448f7b65a7aaf38650f923aa /includes/profiler/output | |
parent | c27b2e832fe25651ef2410fae85b41072aae7519 (diff) |
Update to MediaWiki 1.25.1
Diffstat (limited to 'includes/profiler/output')
-rw-r--r-- | includes/profiler/output/ProfilerOutput.php | 57 | ||||
-rw-r--r-- | includes/profiler/output/ProfilerOutputDb.php | 94 | ||||
-rw-r--r-- | includes/profiler/output/ProfilerOutputDump.php | 51 | ||||
-rw-r--r-- | includes/profiler/output/ProfilerOutputStats.php | 57 | ||||
-rw-r--r-- | includes/profiler/output/ProfilerOutputText.php | 77 | ||||
-rw-r--r-- | includes/profiler/output/ProfilerOutputUdp.php | 96 |
6 files changed, 432 insertions, 0 deletions
diff --git a/includes/profiler/output/ProfilerOutput.php b/includes/profiler/output/ProfilerOutput.php new file mode 100644 index 00000000..3473e0b2 --- /dev/null +++ b/includes/profiler/output/ProfilerOutput.php @@ -0,0 +1,57 @@ +<?php +/** + * 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 + */ + +/** + * Base class for profiling output + * + * Since 1.25 + */ +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; + } + + /** + * Log MediaWiki-style profiling data + * + * @param array $stats Result of Profiler::getFunctionStats() + */ + abstract public function log( array $stats ); +} diff --git a/includes/profiler/output/ProfilerOutputDb.php b/includes/profiler/output/ProfilerOutputDb.php new file mode 100644 index 00000000..76d62d2e --- /dev/null +++ b/includes/profiler/output/ProfilerOutputDb.php @@ -0,0 +1,94 @@ +<?php +/** + * Profiler storing information in the DB. + * + * 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 + */ + +/** + * Logs profiling data into the local DB + * + * @ingroup Profiler + * @since 1.25 + */ +class ProfilerOutputDb extends ProfilerOutput { + /** @var bool Whether to store host data with profiling calls */ + private $perHost = false; + + public function __construct( Profiler $collector, array $params ) { + parent::__construct( $collector, $params ); + global $wgProfilePerHost; + + // Initialize per-host profiling from config, back-compat if available + if ( isset( $this->params['perHost'] ) ) { + $this->perHost = $this->params['perHost']; + } elseif ( $wgProfilePerHost ) { + $this->perHost = $wgProfilePerHost; + } + } + + public function canUse() { + # Do not log anything if database is readonly (bug 5375) + return !wfReadOnly(); + } + + public function log( array $stats ) { + $pfhost = $this->perHost ? wfHostname() : ''; + + try { + $dbw = wfGetDB( DB_MASTER ); + $useTrx = ( $dbw->getType() === 'sqlite' ); // much faster + if ( $useTrx ) { + $dbw->startAtomic( __METHOD__ ); + } + foreach ( $stats as $data ) { + $name = $data['name']; + $eventCount = $data['calls']; + $timeSum = (float)$data['real']; + $memorySum = (float)$data['memory']; + $name = substr( $name, 0, 255 ); + + // Kludge + $timeSum = $timeSum >= 0 ? $timeSum : 0; + $memorySum = $memorySum >= 0 ? $memorySum : 0; + + $dbw->upsert( 'profiling', + array( + 'pf_name' => $name, + 'pf_count' => $eventCount, + 'pf_time' => $timeSum, + 'pf_memory' => $memorySum, + 'pf_server' => $pfhost + ), + array( array( 'pf_name', 'pf_server' ) ), + array( + "pf_count=pf_count+{$eventCount}", + "pf_time=pf_time+{$timeSum}", + "pf_memory=pf_memory+{$memorySum}", + ), + __METHOD__ + ); + } + if ( $useTrx ) { + $dbw->endAtomic( __METHOD__ ); + } + } catch ( DBError $e ) { + } + } +} diff --git a/includes/profiler/output/ProfilerOutputDump.php b/includes/profiler/output/ProfilerOutputDump.php new file mode 100644 index 00000000..bf4b85c2 --- /dev/null +++ b/includes/profiler/output/ProfilerOutputDump.php @@ -0,0 +1,51 @@ +<?php +/** + * Profiler dumping output in xhprof dump file + * + * 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 + */ + +/** + * Profiler dumping output in xhprof dump file + * @ingroup Profiler + * + * @since 1.25 + */ +class ProfilerOutputDump extends ProfilerOutput { + + protected $suffix = ".xhprof"; + + /** + * Can this output type be used? + * + * @return bool + */ + public function canUse() { + if ( empty( $this->params['outputDir'] ) ) { + return false; + } + return true; + } + + public function log( array $stats ) { + $data = $this->collector->getRawData(); + $filename = sprintf( "%s/%s.%s%s", $this->params['outputDir'], uniqid(), $this->collector->getProfileID(), $this->suffix ); + file_put_contents( $filename, serialize( $data ) ); + } +} diff --git a/includes/profiler/output/ProfilerOutputStats.php b/includes/profiler/output/ProfilerOutputStats.php new file mode 100644 index 00000000..ef6ef7c9 --- /dev/null +++ b/includes/profiler/output/ProfilerOutputStats.php @@ -0,0 +1,57 @@ +<?php +/** + * ProfilerOutput class that flushes profiling data to the profiling + * context's stats buffer. + * + * 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 + */ + +/** + * ProfilerOutput class that flushes profiling data to the profiling + * context's stats buffer. + * + * @ingroup Profiler + * @since 1.25 + */ +class ProfilerOutputStats extends ProfilerOutput { + + /** + * Flush profiling data to the current profiling context's stats buffer. + * + * @param array $stats + */ + public function log( array $stats ) { + $contextStats = $this->collector->getContext()->getStats(); + + foreach ( $stats as $stat ) { + // Sanitize the key + $key = str_replace( '::', '.', $stat['name'] ); + $key = preg_replace( '/[^a-z.]+/i', '_', $key ); + $key = trim( $key, '_.' ); + + // Convert fractional seconds to whole milliseconds + $cpu = round( $stat['cpu'] * 1000 ); + $real = round( $stat['real'] * 1000 ); + + $contextStats->increment( "{$key}.calls" ); + $contextStats->timing( "{$key}.cpu", $cpu ); + $contextStats->timing( "{$key}.real", $real ); + } + } +} diff --git a/includes/profiler/output/ProfilerOutputText.php b/includes/profiler/output/ProfilerOutputText.php new file mode 100644 index 00000000..67527798 --- /dev/null +++ b/includes/profiler/output/ProfilerOutputText.php @@ -0,0 +1,77 @@ +<?php +/** + * Profiler showing output in page source. + * + * 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 + */ + +/** + * The least sophisticated profiler output class possible, view your source! :) + * + * @ingroup Profiler + * @since 1.25 + */ +class ProfilerOutputText extends ProfilerOutput { + /** @var float Min real time display threshold */ + protected $thresholdMs; + + function __construct( Profiler $collector, array $params ) { + parent::__construct( $collector, $params ); + $this->thresholdMs = isset( $params['thresholdMs'] ) + ? $params['thresholdMs'] + : .25; + } + public function log( array $stats ) { + if ( $this->collector->getTemplated() ) { + $out = ''; + + // Filter out really tiny entries + $min = $this->thresholdMs; + $stats = array_filter( $stats, function ( $a ) use ( $min ) { + return $a['real'] > $min; + } ); + // Sort descending by time elapsed + usort( $stats, function ( $a, $b ) { + return $a['real'] < $b['real']; + } ); + + array_walk( $stats, + function ( $item ) use ( &$out ) { + $out .= sprintf( "%6.2f%% %3.3f %6d - %s\n", + $item['%real'], $item['real'], $item['calls'], $item['name'] ); + } + ); + + $contentType = $this->collector->getContentType(); + if ( PHP_SAPI === 'cli' ) { + print "<!--\n{$out}\n-->\n"; + } elseif ( $contentType === 'text/html' ) { + $visible = isset( $this->params['visible'] ) ? + $this->params['visible'] : false; + if ( $visible ) { + print "<pre>{$out}</pre>"; + } else { + print "<!--\n{$out}\n-->\n"; + } + } elseif ( $contentType === 'text/javascript' || $contentType === 'text/css' ) { + print "\n/*\n{$out}*/\n"; + } + } + } +} diff --git a/includes/profiler/output/ProfilerOutputUdp.php b/includes/profiler/output/ProfilerOutputUdp.php new file mode 100644 index 00000000..7da03c11 --- /dev/null +++ b/includes/profiler/output/ProfilerOutputUdp.php @@ -0,0 +1,96 @@ +<?php +/** + * Profiler sending messages over UDP. + * + * 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 + */ + +/** + * ProfilerSimpleUDP class, that sends out messages for 'udpprofile' daemon + * (see http://git.wikimedia.org/tree/operations%2Fsoftware.git/master/udpprofile) + * + * @ingroup Profiler + * @since 1.25 + */ +class ProfilerOutputUdp extends ProfilerOutput { + /** @var int port to send profiling data to */ + private $port = 3811; + + /** @var string host to send profiling data to */ + private $host = '127.0.0.1'; + + /** @var string format string for profiling data */ + private $format = "%s - %d %f %f %f %f %s\n"; + + public function __construct( Profiler $collector, array $params ) { + parent::__construct( $collector, $params ); + global $wgUDPProfilerPort, $wgUDPProfilerHost, $wgUDPProfilerFormatString; + + // Initialize port, host, and format from config, back-compat if available + if ( isset( $this->params['udpport'] ) ) { + $this->port = $this->params['udpport']; + } elseif ( $wgUDPProfilerPort ) { + $this->port = $wgUDPProfilerPort; + } + + if ( isset( $this->params['udphost'] ) ) { + $this->host = $this->params['udphost']; + } elseif ( $wgUDPProfilerHost ) { + $this->host = $wgUDPProfilerHost; + } + + if ( isset( $this->params['udpformat'] ) ) { + $this->format = $this->params['udpformat']; + } elseif ( $wgUDPProfilerFormatString ) { + $this->format = $wgUDPProfilerFormatString; + } + } + + public function canUse() { + # Sockets are not enabled + return function_exists( 'socket_create' ); + } + + public function log( array $stats ) { + $sock = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP ); + $plength = 0; + $packet = ""; + foreach ( $stats as $pfdata ) { + $pfline = sprintf( $this->format, + $this->collector->getProfileID(), + $pfdata['calls'], + $pfdata['cpu'] / 1000, // ms => sec + 0.0, // sum of CPU^2 for each invocation (unused) + $pfdata['real'] / 1000, // ms => sec + 0.0, // sum of real^2 for each invocation (unused) + $pfdata['name'], + $pfdata['memory'] + ); + $length = strlen( $pfline ); + if ( $length + $plength > 1400 ) { + socket_sendto( $sock, $packet, $plength, 0, $this->host, $this->port ); + $packet = ""; + $plength = 0; + } + $packet .= $pfline; + $plength += $length; + } + socket_sendto( $sock, $packet, $plength, 0x100, $this->host, $this->port ); + } +} |