Merge "Put the sha1 tag in <revision> and not wrongly in <page>"
[lhc/web/wiklou.git] / includes / profiler / Profiler.php
index 1358828..f6d8b3a 100644 (file)
@@ -13,7 +13,7 @@
  */
 function wfProfileIn( $functionname ) {
        global $wgProfiler;
-       if ( isset( $wgProfiler['class'] ) ) {
+       if ( $wgProfiler instanceof Profiler || isset( $wgProfiler['class'] ) ) {
                Profiler::instance()->profileIn( $functionname );
        }
 }
@@ -24,7 +24,7 @@ function wfProfileIn( $functionname ) {
  */
 function wfProfileOut( $functionname = 'missing' ) {
        global $wgProfiler;
-       if ( isset( $wgProfiler['class'] ) ) {
+       if ( $wgProfiler instanceof Profiler || isset( $wgProfiler['class'] ) ) {
                Profiler::instance()->profileOut( $functionname );
        }
 }
@@ -34,26 +34,21 @@ function wfProfileOut( $functionname = 'missing' ) {
  * @todo document
  */
 class Profiler {
-       var $mStack = array (), $mWorkStack = array (), $mCollated = array ();
-       var $mCalls = array (), $mTotals = array ();
-       var $mTemplated = false;
-       var $mTimeMetric = 'wall';
-       private $mCollateDone = false;
-       protected $mProfileID = false;
+       protected $mStack = array(), $mWorkStack = array (), $mCollated = array (),
+               $mCalls = array (), $mTotals = array ();
+       protected $mTimeMetric = 'wall';
+       protected $mProfileID = false, $mCollateDone = false, $mTemplated = false;
        private static $__instance = null;
 
-       function __construct( $params = null ) {
-               // Push an entry for the pre-profile setup time onto the stack
-               global $wgRequestTime;
-               if ( !empty( $wgRequestTime ) ) {
-                       $this->mWorkStack[] = array( '-total', 0, $wgRequestTime, 0 );
-                       $this->mStack[] = array( '-setup', 1, $wgRequestTime, 0, microtime(true), 0 );
-               } else {
-                       $this->profileIn( '-total' );
-               }
+       function __construct( $params ) {
                if ( isset( $params['timeMetric'] ) ) {
                        $this->mTimeMetric = $params['timeMetric'];
                }
+               if ( isset( $params['profileID'] ) ) {
+                       $this->mProfileID = $params['profileID'];
+               }
+
+               $this->addInitialStack();
        }
 
        /**
@@ -64,12 +59,20 @@ class Profiler {
                if( is_null( self::$__instance ) ) {
                        global $wgProfiler;
                        if( is_array( $wgProfiler ) ) {
-                               $class = isset( $wgProfiler['class'] ) ? $wgProfiler['class'] : 'ProfilerStub';
+                               if( !isset( $wgProfiler['class'] ) ) {
+                                       wfDebug( __METHOD__ . " called without \$wgProfiler['class']"
+                                               . " set, falling back to ProfilerStub for safety\n" );
+                                       $class = 'ProfilerStub';
+                               } else {
+                                       $class = $wgProfiler['class'];
+                               }
                                self::$__instance = new $class( $wgProfiler );
                        } elseif( $wgProfiler instanceof Profiler ) {
                                self::$__instance = $wgProfiler; // back-compat
                        } else {
-                               self::$__instance = new ProfilerStub;
+                               wfDebug( __METHOD__ . ' called with bogus $wgProfiler setting,'
+                                               . " falling back to ProfilerStub for safety\n" );
+                               self::$__instance = new ProfilerStub( $wgProfiler );
                        }
                }
                return self::$__instance;
@@ -104,6 +107,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()
         *
@@ -141,12 +158,12 @@ class Profiler {
                                if( $functionname == 'close' ){
                                        $message = "Profile section ended by close(): {$bit[0]}";
                                        $this->debug( "$message\n" );
-                                       $this->mStack[] = array( $message, 0, '0 0', 0, '0 0', 0 );
+                                       $this->mStack[] = array( $message, 0, 0.0, 0, 0.0, 0 );
                                }
                                elseif( $bit[0] != $functionname ){
                                        $message = "Profiling error: in({$bit[0]}), out($functionname)";
                                        $this->debug( "$message\n" );
-                                       $this->mStack[] = array( $message, 0, '0 0', 0, '0 0', 0 );
+                                       $this->mStack[] = array( $message, 0, 0.0, 0, 0.0, 0 );
                                }
                        //}
                        $bit[] = $time;
@@ -195,6 +212,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 ) ) );
@@ -203,7 +221,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 ){
@@ -242,6 +261,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;
@@ -256,13 +276,31 @@ class Profiler {
                if ( $this->mTimeMetric === 'user' ) {
                        return $this->getUserTime();
                } else {
-                       return microtime(true);
+                       return microtime( true );
                }
        }
 
        function getUserTime() {
                $ru = getrusage();
-               return $ru['ru_utime.tv_sec'].' '.$ru['ru_utime.tv_usec'] / 1e6;
+               return $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
+       }
+
+       private function getInitialTime() {
+               global $wgRequestTime, $wgRUstart;
+
+               if ( $this->mTimeMetric === 'user' ) {
+                       if ( count( $wgRUstart ) ) {
+                               return $wgRUstart['ru_utime.tv_sec'] + $wgRUstart['ru_utime.tv_usec'] / 1e6;
+                       } else {
+                               return null;
+                       }
+               } else {
+                       if ( empty( $wgRequestTime ) ) {
+                               return null;
+                       } else {
+                               return $wgRequestTime;
+                       }
+               }
        }
 
        protected function collateData() {
@@ -344,7 +382,8 @@ class Profiler {
 
        /**
         * Returns a list of profiled functions.
-        * Also log it into the database if $wgProfileToDatabase is set to true.
+        *
+        * @return string
         */
        function getFunctionReport() {
                $this->collateData();
@@ -356,7 +395,7 @@ class Profiler {
                $prof = "\nProfiling data\n";
                $prof .= sprintf( $titleFormat, 'Name', 'Calls', 'Total', 'Each', '%', 'Mem' );
 
-               $total = @$this->mCollated['-total'];
+               $total = isset( $this->mCollated['-total'] ) ? $this->mCollated['-total'] : 0;
 
                foreach( $this->mCollated as $fname => $elapsed ){
                        $calls = $this->mCalls[$fname];
@@ -465,6 +504,7 @@ class Profiler {
 
        /**
         * Get the function name of the current profiling section
+        * @return
         */
        function getCurrentSection() {
                $elt = end( $this->mWorkStack );