Merge "(bug 31704) Allow selection of associated namespace on the watchlist"
[lhc/web/wiklou.git] / includes / profiler / Profiler.php
index 0fe18c2..f2054b5 100644 (file)
@@ -1,12 +1,31 @@
 <?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
  * This file is only included if profiling is enabled
  */
 
+/**
+ * @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();
        }
 
        /**
@@ -114,6 +126,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()
         *
@@ -205,6 +231,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 +240,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 +280,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 +291,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;
@@ -494,6 +564,7 @@ class Profiler {
 
        /**
         * Get the function name of the current profiling section
+        * @return
         */
        function getCurrentSection() {
                $elt = end( $this->mWorkStack );