diff options
Diffstat (limited to 'includes/profiler/Profiler.php')
-rw-r--r-- | includes/profiler/Profiler.php | 174 |
1 files changed, 93 insertions, 81 deletions
diff --git a/includes/profiler/Profiler.php b/includes/profiler/Profiler.php index 62be39e4..5ecdc4f0 100644 --- a/includes/profiler/Profiler.php +++ b/includes/profiler/Profiler.php @@ -28,7 +28,7 @@ /** * Begin profiling of a function - * @param $functionname String: name of the function we will profile + * @param string $functionname name of the function we will profile */ function wfProfileIn( $functionname ) { global $wgProfiler; @@ -39,7 +39,7 @@ function wfProfileIn( $functionname ) { /** * Stop profiling of a function - * @param $functionname String: name of the function we have profiled + * @param string $functionname name of the function we have profiled */ function wfProfileOut( $functionname = 'missing' ) { global $wgProfiler; @@ -157,7 +157,7 @@ class Profiler { */ public function profileIn( $functionname ) { global $wgDebugFunctionEntry; - if( $wgDebugFunctionEntry ){ + if( $wgDebugFunctionEntry ) { $this->debug( str_repeat( ' ', count( $this->mWorkStack ) ) . 'Entering ' . $functionname . "\n" ); } @@ -174,22 +174,22 @@ class Profiler { $memory = memory_get_usage(); $time = $this->getTime(); - if( $wgDebugFunctionEntry ){ + if( $wgDebugFunctionEntry ) { $this->debug( str_repeat( ' ', count( $this->mWorkStack ) - 1 ) . 'Exiting ' . $functionname . "\n" ); } - $bit = array_pop($this->mWorkStack); + $bit = array_pop( $this->mWorkStack ); - if (!$bit) { - $this->debug("Profiling error, !\$bit: $functionname\n"); + if ( !$bit ) { + $this->debug( "Profiling error, !\$bit: $functionname\n" ); } else { - //if( $wgDebugProfiling ){ - if( $functionname == 'close' ){ + //if( $wgDebugProfiling ) { + 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 ); } - elseif( $bit[0] != $functionname ){ + 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 ); @@ -205,7 +205,7 @@ class Profiler { * Close opened profiling sections */ public function close() { - while( count( $this->mWorkStack ) ){ + while( count( $this->mWorkStack ) ) { $this->profileOut( 'close' ); } } @@ -228,7 +228,7 @@ class Profiler { global $wgDebugFunctionEntry, $wgProfileCallTree; $wgDebugFunctionEntry = false; - if( !count( $this->mStack ) && !count( $this->mCollated ) ){ + if( !count( $this->mStack ) && !count( $this->mCollated ) ) { return "No profiling output\n"; } @@ -250,20 +250,20 @@ class Profiler { /** * Recursive function the format the current profiling array into a tree * - * @param $stack array profiling array + * @param array $stack profiling array * @return array */ function remapCallTree( $stack ) { - if( count( $stack ) < 2 ){ + if( count( $stack ) < 2 ) { return $stack; } $outputs = array (); - for( $max = count( $stack ) - 1; $max > 0; ){ + for( $max = count( $stack ) - 1; $max > 0; ) { /* Find all items under this entry */ $level = $stack[$max][1]; $working = array (); - for( $i = $max -1; $i >= 0; $i-- ){ - if( $stack[$i][1] > $level ){ + for( $i = $max -1; $i >= 0; $i-- ) { + if( $stack[$i][1] > $level ) { $working[] = $stack[$i]; } else { break; @@ -271,7 +271,7 @@ class Profiler { } $working = $this->remapCallTree( array_reverse( $working ) ); $output = array(); - foreach( $working as $item ){ + foreach( $working as $item ) { array_push( $output, $item ); } array_unshift( $output, $stack[$max] ); @@ -280,8 +280,8 @@ class Profiler { array_unshift( $outputs, $output ); } $final = array(); - foreach( $outputs as $output ){ - foreach( $output as $item ){ + foreach( $outputs as $output ) { + foreach( $output as $item ) { $final[] = $item; } } @@ -293,9 +293,9 @@ class Profiler { * @return string */ function getCallTreeLine( $entry ) { - list( $fname, $level, $start, /* $x */, $end) = $entry; + list( $fname, $level, $start, /* $x */, $end ) = $entry; $delta = $end - $start; - $space = str_repeat(' ', $level); + $space = str_repeat( ' ', $level ); # The ugly double sprintf is to work around a PHP bug, # which has been fixed in recent releases. return sprintf( "%10s %s %s\n", trim( sprintf( "%7.3f", $delta * 1000.0 ) ), $space, $fname ); @@ -305,7 +305,7 @@ class Profiler { * 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: + * @param string|false $metric 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 @@ -338,7 +338,7 @@ class Profiler { * 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: + * @param string|false $metric 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 @@ -386,23 +386,23 @@ class Profiler { $this->mMemory = array(); # Estimate profiling overhead - $profileCount = count($this->mStack); + $profileCount = count( $this->mStack ); self::calculateOverhead( $profileCount ); # First, subtract the overhead! $overheadTotal = $overheadMemory = $overheadInternal = array(); - foreach( $this->mStack as $entry ){ + foreach( $this->mStack as $entry ) { $fname = $entry[0]; $start = $entry[2]; $end = $entry[4]; $elapsed = $end - $start; $memory = $entry[5] - $entry[3]; - if( $fname == '-overhead-total' ){ + if( $fname == '-overhead-total' ) { $overheadTotal[] = $elapsed; $overheadMemory[] = $memory; } - elseif( $fname == '-overhead-internal' ){ + elseif( $fname == '-overhead-internal' ) { $overheadInternal[] = $elapsed; } } @@ -411,7 +411,7 @@ class Profiler { $overheadInternal = $overheadInternal ? array_sum( $overheadInternal ) / count( $overheadInternal ) : 0; # Collate - foreach( $this->mStack as $index => $entry ){ + foreach( $this->mStack as $index => $entry ) { $fname = $entry[0]; $start = $entry[2]; $end = $entry[4]; @@ -420,7 +420,7 @@ class Profiler { $memory = $entry[5] - $entry[3]; $subcalls = $this->calltreeCount( $this->mStack, $index ); - if( !preg_match( '/^-overhead/', $fname ) ){ + if( !preg_match( '/^-overhead/', $fname ) ) { # Adjust for profiling overhead (except special values with elapsed=0 if( $elapsed ) { $elapsed -= $overheadInternal; @@ -429,7 +429,7 @@ class Profiler { } } - if( !array_key_exists( $fname, $this->mCollated ) ){ + if( !array_key_exists( $fname, $this->mCollated ) ) { $this->mCollated[$fname] = 0; $this->mCalls[$fname] = 0; $this->mMemory[$fname] = 0; @@ -441,8 +441,8 @@ class Profiler { $this->mCollated[$fname] += $elapsed; $this->mCalls[$fname]++; $this->mMemory[$fname] += $memory; - $this->mMin[$fname] = min($this->mMin[$fname], $elapsed); - $this->mMax[$fname] = max($this->mMax[$fname], $elapsed); + $this->mMin[$fname] = min( $this->mMin[$fname], $elapsed ); + $this->mMax[$fname] = max( $this->mMax[$fname], $elapsed ); $this->mOverhead[$fname] += $subcalls; } @@ -460,18 +460,18 @@ class Profiler { $width = 140; $nameWidth = $width - 65; - $format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d (%13.3f -%13.3f) [%d]\n"; + $format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d (%13.3f -%13.3f) [%d]\n"; $titleFormat = "%-{$nameWidth}s %6s %13s %13s %13s %9s\n"; $prof = "\nProfiling data\n"; $prof .= sprintf( $titleFormat, 'Name', 'Calls', 'Total', 'Each', '%', 'Mem' ); $total = isset( $this->mCollated['-total'] ) ? $this->mCollated['-total'] : 0; - foreach( $this->mCollated as $fname => $elapsed ){ + foreach( $this->mCollated as $fname => $elapsed ) { $calls = $this->mCalls[$fname]; $percent = $total ? 100. * $elapsed / $total : 0; $memory = $this->mMemory[$fname]; - $prof .= sprintf($format, substr($fname, 0, $nameWidth), $calls, (float) ($elapsed * 1000), (float) ($elapsed * 1000) / $calls, $percent, $memory, ($this->mMin[$fname] * 1000.0), ($this->mMax[$fname] * 1000.0), $this->mOverhead[$fname]); + $prof .= sprintf( $format, substr( $fname, 0, $nameWidth ), $calls, (float) ($elapsed * 1000), (float) ($elapsed * 1000) / $calls, $percent, $memory, ( $this->mMin[$fname] * 1000.0 ), ( $this->mMax[$fname] * 1000.0 ), $this->mOverhead[$fname] ); } $prof .= "\nTotal: $total\n\n"; @@ -483,7 +483,7 @@ class Profiler { */ protected static function calculateOverhead( $profileCount ) { wfProfileIn( '-overhead-total' ); - for( $i = 0; $i < $profileCount; $i++ ){ + for( $i = 0; $i < $profileCount; $i++ ) { wfProfileIn( '-overhead-internal' ); wfProfileOut( '-overhead-internal' ); } @@ -499,10 +499,10 @@ class Profiler { * @return Integer * @private */ - function calltreeCount($stack, $start) { + function calltreeCount( $stack, $start ) { $level = $stack[$start][1]; $count = 0; - for ($i = $start -1; $i >= 0 && $stack[$i][1] > $level; $i --) { + for ( $i = $start -1; $i >= 0 && $stack[$i][1] > $level; $i-- ) { $count ++; } return $count; @@ -511,7 +511,7 @@ class Profiler { /** * Log the whole profiling data into the database. */ - public function logData(){ + public function logData() { global $wgProfilePerHost, $wgProfileToDatabase; # Do not log anything if database is readonly (bug 5375) @@ -524,52 +524,50 @@ class Profiler { return; } - $errorState = $dbw->ignoreErrors( true ); - - if( $wgProfilePerHost ){ + if( $wgProfilePerHost ) { $pfhost = wfHostname(); } else { $pfhost = ''; } - $this->collateData(); - - foreach( $this->mCollated as $name => $elapsed ){ - $eventCount = $this->mCalls[$name]; - $timeSum = (float) ($elapsed * 1000); - $memorySum = (float)$this->mMemory[$name]; - $name = substr($name, 0, 255); - - // Kludge - $timeSum = ($timeSum >= 0) ? $timeSum : 0; - $memorySum = ($memorySum >= 0) ? $memorySum : 0; - - $dbw->update( 'profiling', - array( - "pf_count=pf_count+{$eventCount}", - "pf_time=pf_time+{$timeSum}", - "pf_memory=pf_memory+{$memorySum}", - ), - array( - 'pf_name' => $name, - 'pf_server' => $pfhost, - ), - __METHOD__ ); - - $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 ), - __METHOD__, array ('IGNORE')); + try { + $this->collateData(); + + foreach( $this->mCollated as $name => $elapsed ) { + $eventCount = $this->mCalls[$name]; + $timeSum = (float) ($elapsed * 1000); + $memorySum = (float)$this->mMemory[$name]; + $name = substr($name, 0, 255); + + // Kludge + $timeSum = ($timeSum >= 0) ? $timeSum : 0; + $memorySum = ($memorySum >= 0) ? $memorySum : 0; + + $dbw->update( 'profiling', + array( + "pf_count=pf_count+{$eventCount}", + "pf_time=pf_time+{$timeSum}", + "pf_memory=pf_memory+{$memorySum}", + ), + array( + 'pf_name' => $name, + 'pf_server' => $pfhost, + ), + __METHOD__ ); + + $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 ), + __METHOD__, array ( 'IGNORE' ) ); + } + // When we upgrade to mysql 4.1, the insert+update + // can be merged into just a insert with this construct added: + // "ON DUPLICATE KEY UPDATE ". + // "pf_count=pf_count + VALUES(pf_count), ". + // "pf_time=pf_time + VALUES(pf_time)"; } - // When we upgrade to mysql 4.1, the insert+update - // can be merged into just a insert with this construct added: - // "ON DUPLICATE KEY UPDATE ". - // "pf_count=pf_count + VALUES(pf_count), ". - // "pf_time=pf_time + VALUES(pf_time)"; - } - - $dbw->ignoreErrors( $errorState ); + } catch ( DBError $e ) {} } /** @@ -584,11 +582,25 @@ class Profiler { /** * Add an entry in the debug log file * - * @param $s String to output + * @param string $s to output */ function debug( $s ) { if( defined( 'MW_COMPILED' ) || function_exists( 'wfDebug' ) ) { wfDebug( $s ); } } + + /** + * Get the content type sent out to the client. + * Used for profilers that output instead of store data. + * @return string + */ + protected function getContentType() { + foreach ( headers_list() as $header ) { + if ( preg_match( '#^content-type: (\w+/\w+);?#i', $header, $m ) ) { + return $m[1]; + } + } + return null; + } } |