Make profiling to UDP work again
[lhc/web/wiklou.git] / includes / profiler / ProfilerMwprof.php
index e81c6ec..67b6034 100644 (file)
  * @since 1.23
  */
 class ProfilerMwprof extends Profiler {
-
        // Message types
-
-       const TYPE_SINGLE  = 1;
+       const TYPE_SINGLE = 1;
        const TYPE_RUNNING = 2;
 
+       protected function collateOnly() {
+               return false;
+       }
+
        /**
         * Indicate that this Profiler subclass is persistent.
         *
@@ -62,18 +64,7 @@ class ProfilerMwprof extends Profiler {
         */
        public function profileIn( $inName ) {
                $this->mWorkStack[] = array( $inName, count( $this->mWorkStack ),
-                       $this->getTime(), $this->getTime( 'cpu' ) );
-       }
-
-       /**
-        * Produce an empty function report.
-        *
-        * ProfileMwprof does not provide a function report.
-        *
-        * @return string Empty string.
-        */
-       public function getFunctionReport() {
-               return '';
+                       $this->getTime(), $this->getTime( 'cpu' ), 0 );
        }
 
        /**
@@ -90,13 +81,13 @@ class ProfilerMwprof extends Profiler {
                // Check for unbalanced profileIn / profileOut calls.
                // Bad entries are logged but not sent.
                if ( $inName !== $outName ) {
-                       wfDebugLog( 'ProfilerUnbalanced', json_encode( array( $inName, $outName ) ) );
+                       $this->debugGroup( 'ProfilerUnbalanced', json_encode( array( $inName, $outName ) ) );
                        return;
                }
 
                $elapsedCpu = $this->getTime( 'cpu' ) - $inCpu;
                $elapsedWall = $this->getTime() - $inWall;
-               $this->updateEntry( $outName, $elapsedCpu, $elapsedWall );
+               $this->updateRunningEntry( $outName, $elapsedCpu, $elapsedWall );
                $this->updateTrxProfiling( $outName, $elapsedWall );
        }
 
@@ -107,7 +98,7 @@ class ProfilerMwprof extends Profiler {
         * @param float $elapsedCpu elapsed CPU time
         * @param float $elapsedWall elapsed wall-clock time
         */
-       public function updateEntry( $name, $elapsedCpu, $elapsedWall ) {
+       public function updateRunningEntry( $name, $elapsedCpu, $elapsedWall ) {
                // If this is the first measurement for this entry, store plain values.
                // Many profiled functions will only be called once per request.
                if ( !isset( $this->mCollated[$name] ) ) {
@@ -138,6 +129,77 @@ class ProfilerMwprof extends Profiler {
                $entry['wall']->push( $elapsedWall );
        }
 
+       /**
+        * Produce an empty function report.
+        *
+        * ProfileMwprof does not provide a function report.
+        *
+        * @return string Empty string.
+        */
+       public function getFunctionReport() {
+               return '';
+       }
+
+       /**
+        * @return array
+        */
+       public function getRawData() {
+               // This method is called before shutdown in the footer method on Skins.
+               // If some outer methods have not yet called wfProfileOut(), work around
+               // that by clearing anything in the work stack to just the "-total" entry.
+               if ( count( $this->mWorkStack ) > 1 ) {
+                       $oldWorkStack = $this->mWorkStack;
+                       $this->mWorkStack = array( $this->mWorkStack[0] ); // just the "-total" one
+               } else {
+                       $oldWorkStack = null;
+               }
+               $this->close();
+               // If this trick is used, then the old work stack is swapped back afterwards.
+               // This means that logData() will still make use of all the method data since
+               // the missing wfProfileOut() calls should be made by the time it is called.
+               if ( $oldWorkStack ) {
+                       $this->mWorkStack = $oldWorkStack;
+               }
+
+               $totalWall = 0.0;
+               $profile = array();
+               foreach ( $this->mCollated as $fname => $data ) {
+                       if ( $data['count'] == 1 ) {
+                               $profile[] = array(
+                                       'name' => $fname,
+                                       'calls' => $data['count'],
+                                       'elapsed' => $data['wall'] * 1000,
+                                       'memory' => 0, // not supported
+                                       'min' => $data['wall'] * 1000,
+                                       'max' => $data['wall'] * 1000,
+                                       'overhead' => 0, // not supported
+                                       'periods' => array() // not supported
+                               );
+                               $totalWall += $data['wall'];
+                       } else {
+                               $profile[] = array(
+                                       'name' => $fname,
+                                       'calls' => $data['count'],
+                                       'elapsed' => $data['wall']->n * $data['wall']->getMean() * 1000,
+                                       'memory' => 0, // not supported
+                                       'min' => $data['wall']->min * 1000,
+                                       'max' => $data['wall']->max * 1000,
+                                       'overhead' => 0, // not supported
+                                       'periods' => array() // not supported
+                               );
+                               $totalWall += $data['wall']->n * $data['wall']->getMean();
+                       }
+               }
+               $totalWall = $totalWall * 1000;
+
+               foreach ( $profile as &$item ) {
+                       $item['percent'] = $totalWall ? 100 * $item['elapsed'] / $totalWall : 0;
+                       $z+= $item['percent'];
+               }
+
+               return $profile;
+       }
+
        /**
         * Serialize profiling data and send to a profiling data aggregator.
         *
@@ -151,6 +213,11 @@ class ProfilerMwprof extends Profiler {
 
                $this->close();
 
+               if ( !function_exists( 'socket_create' ) ) {
+                       #trigger_error( __METHOD__ . ": function \"socket_create\" not found." );
+                       return; // avoid fatal
+               }
+
                $sock = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
                socket_connect( $sock, $wgUDPProfilerHost, $wgUDPProfilerPort );
                $bufferLength = 0;