00001 <?php
00002
# This file is only included if profiling is enabled
00003 function
wfProfileIn( $functionname )
00004 {
00005 global
$wgProfiler;
00006
$wgProfiler->profileIn( $functionname );
00007 }
00008
00009 function
wfProfileOut( $functionname =
"missing" )
00010 {
00011 global
$wgProfiler;
00012
$wgProfiler->profileOut( $functionname );
00013 }
00014
00015 function
wfGetProfilingOutput( $start, $elapsed ) {
00016 global
$wgProfiler;
00017
return $wgProfiler->getOutput( $start, $elapsed );
00018 }
00019
00020 function
wfProfileClose()
00021 {
00022 global
$wgProfiler;
00023
$wgProfiler->close();
00024 }
00025
00026 class Profiler
00027 {
00028 var
$mStack = array(), $mWorkStack = array(), $mCollated = array();
00029 var
$mCalls = array(), $mTotals = array();
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 function
profileIn( $functionname )
00040 {
00041 global
$wgDebugFunctionEntry;
00042
if (
$wgDebugFunctionEntry && function_exists(
"wfDebug" ) ) {
00043
wfDebug(
"Entering $functionname\n" );
00044 }
00045 array_push( $this->mWorkStack, array($functionname, count( $this->mWorkStack ), microtime() ) );
00046 }
00047
00048 function
profileOut( $functionname)
00049 {
00050 global
$wgDebugProfiling,
$wgDebugFunctionEntry;
00051
00052
if (
$wgDebugFunctionEntry && function_exists(
"wfDebug" ) ) {
00053
wfDebug(
"Exiting $functionname\n" );
00054 }
00055
00056 $bit = array_pop( $this->mWorkStack );
00057
00058
if ( !$bit ) {
00059
wfDebug(
"Profiling error, !\$bit: $functionname\n" );
00060 }
else {
00061
if (
$wgDebugProfiling ) {
00062
if ( $functionname ==
"close" ) {
00063
wfDebug(
"Profile section ended by close(): {$bit[0]}\n" );
00064 } elseif ( $bit[0] != $functionname ) {
00065
wfDebug(
"Profiling error: in({$bit[0]}), out($functionname)\n" );
00066 }
00067 }
00068 array_push( $bit, microtime() );
00069 array_push( $this->mStack, $bit );
00070 }
00071 }
00072
00073 function
close()
00074 {
00075
while ( count( $this->mWorkStack ) ) {
00076 $this->profileOut(
"close" );
00077 }
00078 }
00079
00080 function
getOutput( $scriptStart, $scriptElapsed )
00081 {
00082
if( !count( $this->mStack ) ) {
00083
return "No profiling output\n";
00084 }
00085 $this->
close();
00086
$width = 125;
00087 $format =
"%-" . (
$width - 28) .
"s %6d %6.3f %6.3f %6.3f%%\n";
00088 $titleFormat =
"%-" . (
$width - 28) .
"s %9s %9s %9s %9s\n";
00089 $prof =
"\nProfiling data\n";
00090 $prof .= sprintf( $titleFormat,
"Name",
"Calls",
"Total",
"Each",
"%" );
00091 $this->mCollated = array();
00092 $this->mCalls = array();
00093
00094
# Estimate profiling overhead
00095
$profileCount = count( $this->mStack );
00096
wfProfileIn(
"-overhead-total" );
00097
for (
$i=0;
$i<$profileCount ;
$i++) {
00098
wfProfileIn(
"-overhead-internal" );
00099
wfProfileOut(
"-overhead-internal" );
00100 }
00101
wfProfileOut(
"-overhead-total" );
00102
00103
# Collate
00104
foreach ( $this->mStack as $entry ) {
00105 $fname = $entry[0];
00106 $thislevel = $entry[1];
00107 $start = explode(
" ", $entry[2]);
00108 $start = (
float)$start[0] + (
float)$start[1];
00109 $end = explode(
" ", $entry[3]);
00110 $end = (
float)$end[0] + (
float)$end[1];
00111 $elapsed = $end - $start;
00112
00113
if ( !array_key_exists( $fname, $this->mCollated ) ) {
00114 $this->mCollated[$fname] = 0;
00115 $this->mCalls[$fname] = 0;
00116 }
00117
00118 $this->mCollated[$fname] += $elapsed;
00119 $this->mCalls[$fname] ++;
00120 }
00121
00122 $total = @$this->mCollated[
"-total"];
00123 $overhead = $this->mCollated[
"-overhead-internal"] / $profileCount;
00124 $this->mCalls[
"-overhead-total"] = $profileCount;
00125
00126
# Output
00127
foreach ( $this->mCollated as $fname => $elapsed ) {
00128 $calls = $this->mCalls[$fname];
00129
# Adjust for overhead
00130
if ( $fname[0] !=
"-" ) {
00131 $elapsed -= $overhead * $calls;
00132 }
00133
00134 $percent = $total ? 100. * $elapsed / $total : 0;
00135 $prof .= sprintf( $format, $fname, $calls, (
float)($elapsed * 1000),
00136 (
float)($elapsed * 1000) / $calls, $percent );
00137
00138 global
$wgProfileToDatabase;
00139
if(
$wgProfileToDatabase ) {
00140
Profiler::logToDB( $fname, (
float)($elapsed * 1000), $calls );
00141 }
00142 }
00143 $prof .=
"\nTotal: $total\n\n";
00144
00145
return $prof;
00146 }
00147
00148
00149 function
logToDB($name, $timeSum, $eventCount)
00150 {
00151 $name =
wfStrencode( $
name );
00152
$sql =
"UPDATE profiling ".
00153
"SET pf_count=pf_count+{$eventCount}, ".
00154
"pf_time=pf_time + {$timeSum} ".
00155
"WHERE pf_name='{$name}'";
00156
wfQuery($sql ,
DB_WRITE);
00157
00158 $rc =
wfAffectedRows();
00159
if( $rc == 0) {
00160
$sql =
"INSERT IGNORE INTO profiling (pf_name,pf_count,pf_time) ".
00161
"VALUES ('{$name}', {$eventCount}, {$timeSum}) ";
00162
wfQuery($sql ,
DB_WRITE);
00163 $rc =
wfAffectedRows();
00164 }
00165
00166
00167
00168
00169
00170 }
00171
00172 }
00173
00174
00175 $wgProfiler =
new Profiler();
00176
$wgProfiler->profileIn(
"-total" );
00177 ?>