diff options
Diffstat (limited to 'includes/profiler')
-rw-r--r-- | includes/profiler/Profiler.php | 131 | ||||
-rw-r--r-- | includes/profiler/ProfilerSimple.php | 78 | ||||
-rw-r--r-- | includes/profiler/ProfilerSimpleText.php | 17 | ||||
-rw-r--r-- | includes/profiler/ProfilerSimpleTrace.php | 36 | ||||
-rw-r--r-- | includes/profiler/ProfilerSimpleUDP.php | 21 | ||||
-rw-r--r-- | includes/profiler/ProfilerStub.php | 27 |
6 files changed, 238 insertions, 72 deletions
diff --git a/includes/profiler/Profiler.php b/includes/profiler/Profiler.php index 0fe18c25..62be39e4 100644 --- a/includes/profiler/Profiler.php +++ b/includes/profiler/Profiler.php @@ -1,6 +1,21 @@ <?php /** - * @defgroup Profiler Profiler + * Base class and functions for profiling. + * + * 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 @@ -8,6 +23,10 @@ */ /** + * @defgroup Profiler Profiler + */ + +/** * Begin profiling of a function * @param $functionname String: name of the function we will profile */ @@ -48,14 +67,7 @@ class Profiler { $this->mProfileID = $params['profileID']; } - // Push an entry for the pre-profile setup time onto the stack - $initial = $this->getInitialTime(); - if ( $initial !== null ) { - $this->mWorkStack[] = array( '-total', 0, $initial, 0 ); - $this->mStack[] = array( '-setup', 1, $initial, 0, $this->getTime(), 0 ); - } else { - $this->profileIn( '-total' ); - } + $this->addInitialStack(); } /** @@ -102,6 +114,16 @@ class Profiler { return false; } + /** + * Return whether this profiler stores data + * + * @see Profiler::logData() + * @return Boolean + */ + public function isPersistent() { + return true; + } + public function setProfileID( $id ) { $this->mProfileID = $id; } @@ -115,6 +137,20 @@ class Profiler { } /** + * Add the inital item in the stack. + */ + protected function addInitialStack() { + // Push an entry for the pre-profile setup time onto the stack + $initial = $this->getInitialTime(); + if ( $initial !== null ) { + $this->mWorkStack[] = array( '-total', 0, $initial, 0 ); + $this->mStack[] = array( '-setup', 1, $initial, 0, $this->getTime(), 0 ); + } else { + $this->profileIn( '-total' ); + } + } + + /** * Called by wfProfieIn() * * @param $functionname String @@ -205,6 +241,7 @@ class Profiler { /** * Returns a tree of function call instead of a list of functions + * @return string */ function getCallTree() { return implode( '', array_map( array( &$this, 'getCallTreeLine' ), $this->remapCallTree( $this->mStack ) ) ); @@ -213,7 +250,8 @@ class Profiler { /** * Recursive function the format the current profiling array into a tree * - * @param $stack profiling array + * @param $stack array profiling array + * @return array */ function remapCallTree( $stack ) { if( count( $stack ) < 2 ){ @@ -252,6 +290,7 @@ class Profiler { /** * Callback to get a formatted line for the call tree + * @return string */ function getCallTreeLine( $entry ) { list( $fname, $level, $start, /* $x */, $end) = $entry; @@ -262,28 +301,69 @@ class Profiler { return sprintf( "%10s %s %s\n", trim( sprintf( "%7.3f", $delta * 1000.0 ) ), $space, $fname ); } - function getTime() { - if ( $this->mTimeMetric === 'user' ) { - return $this->getUserTime(); + /** + * Get the initial time of the request, based either on $wgRequestTime or + * $wgRUstart. Will return null if not able to find data. + * + * @param $metric string|false: metric to use, with the following possibilities: + * - user: User CPU time (without system calls) + * - cpu: Total CPU time (user and system calls) + * - wall (or any other string): elapsed time + * - false (default): will fall back to default metric + * @return float|null + */ + function getTime( $metric = false ) { + if ( $metric === false ) { + $metric = $this->mTimeMetric; + } + + if ( $metric === 'cpu' || $this->mTimeMetric === 'user' ) { + if ( !function_exists( 'getrusage' ) ) { + return 0; + } + $ru = getrusage(); + $time = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6; + if ( $metric === 'cpu' ) { + # This is the time of system calls, added to the user time + # it gives the total CPU time + $time += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6; + } + return $time; } else { return microtime( true ); } } - function getUserTime() { - $ru = getrusage(); - return $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6; - } - - private function getInitialTime() { + /** + * Get the initial time of the request, based either on $wgRequestTime or + * $wgRUstart. Will return null if not able to find data. + * + * @param $metric string|false: metric to use, with the following possibilities: + * - user: User CPU time (without system calls) + * - cpu: Total CPU time (user and system calls) + * - wall (or any other string): elapsed time + * - false (default): will fall back to default metric + * @return float|null + */ + protected function getInitialTime( $metric = false ) { global $wgRequestTime, $wgRUstart; - if ( $this->mTimeMetric === 'user' ) { - if ( count( $wgRUstart ) ) { - return $wgRUstart['ru_utime.tv_sec'] + $wgRUstart['ru_utime.tv_usec'] / 1e6; - } else { + if ( $metric === false ) { + $metric = $this->mTimeMetric; + } + + if ( $metric === 'cpu' || $this->mTimeMetric === 'user' ) { + if ( !count( $wgRUstart ) ) { return null; } + + $time = $wgRUstart['ru_utime.tv_sec'] + $wgRUstart['ru_utime.tv_usec'] / 1e6; + if ( $metric === 'cpu' ) { + # This is the time of system calls, added to the user time + # it gives the total CPU time + $time += $wgRUstart['ru_stime.tv_sec'] + $wgRUstart['ru_stime.tv_usec'] / 1e6; + } + return $time; } else { if ( empty( $wgRequestTime ) ) { return null; @@ -409,7 +489,7 @@ class Profiler { } wfProfileOut( '-overhead-total' ); } - + /** * Counts the number of profiled function calls sitting under * the given point in the call graph. Not the most efficient algo. @@ -479,7 +559,7 @@ class Profiler { $rc = $dbw->affectedRows(); if ( $rc == 0 ) { $dbw->insert('profiling', array ('pf_name' => $name, 'pf_count' => $eventCount, - 'pf_time' => $timeSum, 'pf_memory' => $memorySum, 'pf_server' => $pfhost ), + 'pf_time' => $timeSum, 'pf_memory' => $memorySum, 'pf_server' => $pfhost ), __METHOD__, array ('IGNORE')); } // When we upgrade to mysql 4.1, the insert+update @@ -494,6 +574,7 @@ class Profiler { /** * Get the function name of the current profiling section + * @return */ function getCurrentSection() { $elt = end( $this->mWorkStack ); diff --git a/includes/profiler/ProfilerSimple.php b/includes/profiler/ProfilerSimple.php index 055a0ea0..d1d1c5d9 100644 --- a/includes/profiler/ProfilerSimple.php +++ b/includes/profiler/ProfilerSimple.php @@ -1,5 +1,22 @@ <?php /** + * Base class for simple profiling. + * + * 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 */ @@ -15,32 +32,24 @@ class ProfilerSimple extends Profiler { var $zeroEntry = array('cpu'=> 0.0, 'cpu_sq' => 0.0, 'real' => 0.0, 'real_sq' => 0.0, 'count' => 0); var $errorEntry; - function __construct( $params ) { - global $wgRequestTime, $wgRUstart; - parent::__construct( $params ); + public function isPersistent() { + /* Implement in output subclasses */ + return false; + } + protected function addInitialStack() { $this->errorEntry = $this->zeroEntry; $this->errorEntry['count'] = 1; - if (!empty($wgRequestTime) && !empty($wgRUstart)) { - # Remove the -total entry from parent::__construct - $this->mWorkStack = array(); - - $this->mWorkStack[] = array( '-total', 0, $wgRequestTime,$this->getCpuTime($wgRUstart)); - - $elapsedcpu = $this->getCpuTime() - $this->getCpuTime($wgRUstart); - $elapsedreal = microtime(true) - $wgRequestTime; + $initialTime = $this->getInitialTime(); + $initialCpu = $this->getInitialTime( 'cpu' ); + if ( $initialTime !== null && $initialCpu !== null ) { + $this->mWorkStack[] = array( '-total', 0, $initialTime, $initialCpu ); + $this->mWorkStack[] = array( '-setup', 1, $initialTime, $initialCpu ); - $entry =& $this->mCollated["-setup"]; - if (!is_array($entry)) { - $entry = $this->zeroEntry; - $this->mCollated["-setup"] =& $entry; - } - $entry['cpu'] += $elapsedcpu; - $entry['cpu_sq'] += $elapsedcpu*$elapsedcpu; - $entry['real'] += $elapsedreal; - $entry['real_sq'] += $elapsedreal*$elapsedreal; - $entry['count']++; + $this->profileOut( '-setup' ); + } else { + $this->profileIn( '-total' ); } } @@ -53,7 +62,7 @@ class ProfilerSimple extends Profiler { if ($wgDebugFunctionEntry) { $this->debug(str_repeat(' ', count($this->mWorkStack)).'Entering '.$functionname."\n"); } - $this->mWorkStack[] = array($functionname, count( $this->mWorkStack ), microtime(true), $this->getCpuTime()); + $this->mWorkStack[] = array( $functionname, count( $this->mWorkStack ), $this->getTime(), $this->getTime( 'cpu' ) ); } function profileOut($functionname) { @@ -80,8 +89,8 @@ class ProfilerSimple extends Profiler { $this->mCollated[$message] = $this->errorEntry; } $entry =& $this->mCollated[$functionname]; - $elapsedcpu = $this->getCpuTime() - $octime; - $elapsedreal = microtime(true) - $ortime; + $elapsedcpu = $this->getTime( 'cpu' ) - $octime; + $elapsedreal = $this->getTime() - $ortime; if (!is_array($entry)) { $entry = $this->zeroEntry; $this->mCollated[$functionname] =& $entry; @@ -104,15 +113,20 @@ class ProfilerSimple extends Profiler { /* Implement in subclasses */ } - function getCpuTime($ru=null) { - if ( function_exists( 'getrusage' ) ) { - if ( $ru == null ) { - $ru = getrusage(); - } - return ($ru['ru_utime.tv_sec'] + $ru['ru_stime.tv_sec'] + ($ru['ru_utime.tv_usec'] + - $ru['ru_stime.tv_usec']) * 1e-6); + /** + * Get the actual CPU time or the initial one if $ru is set. + * + * @deprecated in 1.20 + * @return float|null + */ + function getCpuTime( $ru = null ) { + wfDeprecated( __METHOD__, '1.20' ); + + if ( $ru === null ) { + return $this->getTime( 'cpu' ); } else { - return 0; + # It theory we should use $ru here, but it always $wgRUstart that is passed here + return $this->getInitialTime( 'cpu' ); } } } diff --git a/includes/profiler/ProfilerSimpleText.php b/includes/profiler/ProfilerSimpleText.php index 3621a41f..3e7d6fa4 100644 --- a/includes/profiler/ProfilerSimpleText.php +++ b/includes/profiler/ProfilerSimpleText.php @@ -1,5 +1,22 @@ <?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 */ diff --git a/includes/profiler/ProfilerSimpleTrace.php b/includes/profiler/ProfilerSimpleTrace.php index 784609f5..822e9fe4 100644 --- a/includes/profiler/ProfilerSimpleTrace.php +++ b/includes/profiler/ProfilerSimpleTrace.php @@ -1,5 +1,22 @@ <?php /** + * Profiler showing execution trace. + * + * 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 */ @@ -10,20 +27,11 @@ * @ingroup Profiler */ class ProfilerSimpleTrace extends ProfilerSimple { - var $trace = ""; + var $trace = "Beginning trace: \n"; var $memory = 0; - function __construct( $params ) { - global $wgRequestTime, $wgRUstart; - parent::__construct( $params ); - if ( !empty( $wgRequestTime ) && !empty( $wgRUstart ) ) { - $this->mWorkStack[] = array( '-total', 0, $wgRequestTime, $this->getCpuTime( $wgRUstart ) ); - } - $this->trace .= "Beginning trace: \n"; - } - - function profileIn($functionname) { - $this->mWorkStack[] = array($functionname, count( $this->mWorkStack ), microtime(true), $this->getCpuTime()); + function profileIn( $functionname ) { + parent::profileIn( $functionname ); $this->trace .= " " . sprintf("%6.1f",$this->memoryDiff()) . str_repeat( " ", count($this->mWorkStack)) . " > " . $functionname . "\n"; } @@ -48,12 +56,12 @@ class ProfilerSimpleTrace extends ProfilerSimple { elseif ( $ofname != $functionname ) { $this->trace .= "Profiling error: in({$ofname}), out($functionname)"; } - $elapsedreal = microtime( true ) - $ortime; + $elapsedreal = $this->getTime() - $ortime; $this->trace .= sprintf( "%03.6f %6.1f", $elapsedreal, $this->memoryDiff() ) . str_repeat(" ", count( $this->mWorkStack ) + 1 ) . " < " . $functionname . "\n"; } } - + function memoryDiff() { $diff = memory_get_usage() - $this->memory; $this->memory = memory_get_usage(); diff --git a/includes/profiler/ProfilerSimpleUDP.php b/includes/profiler/ProfilerSimpleUDP.php index ae607aa6..a95ccb0d 100644 --- a/includes/profiler/ProfilerSimpleUDP.php +++ b/includes/profiler/ProfilerSimpleUDP.php @@ -1,5 +1,22 @@ <?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 */ @@ -10,6 +27,10 @@ * @ingroup Profiler */ class ProfilerSimpleUDP extends ProfilerSimple { + public function isPersistent() { + return true; + } + public function logData() { global $wgUDPProfilerHost, $wgUDPProfilerPort; diff --git a/includes/profiler/ProfilerStub.php b/includes/profiler/ProfilerStub.php index 1a0933c4..c0eb0fb4 100644 --- a/includes/profiler/ProfilerStub.php +++ b/includes/profiler/ProfilerStub.php @@ -1,13 +1,38 @@ <?php /** - * Stub profiling functions + * Stub profiling functions. + * + * 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 */ + +/** + * Stub profiler that does nothing + * + * @ingroup Profiler + */ class ProfilerStub extends Profiler { public function isStub() { return true; } + public function isPersistent() { + return false; + } public function profileIn( $fn ) {} public function profileOut( $fn ) {} public function getOutput() {} |