diff options
Diffstat (limited to 'includes/profiler/Profiler.php')
-rw-r--r-- | includes/profiler/Profiler.php | 131 |
1 files changed, 106 insertions, 25 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 ); |