summaryrefslogtreecommitdiff
path: root/includes/profiler
diff options
context:
space:
mode:
Diffstat (limited to 'includes/profiler')
-rw-r--r--includes/profiler/Profiler.php131
-rw-r--r--includes/profiler/ProfilerSimple.php78
-rw-r--r--includes/profiler/ProfilerSimpleText.php17
-rw-r--r--includes/profiler/ProfilerSimpleTrace.php36
-rw-r--r--includes/profiler/ProfilerSimpleUDP.php21
-rw-r--r--includes/profiler/ProfilerStub.php27
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() {}