2 # This file is only included if profiling is enabled
3 function wfProfileIn( $functionname )
6 $wgProfiler->profileIn( $functionname );
9 function wfProfileOut( $functionname = "missing" )
12 $wgProfiler->profileOut( $functionname );
15 function wfGetProfilingOutput( $start, $elapsed ) {
17 return $wgProfiler->getOutput( $start, $elapsed );
20 function wfProfileClose()
26 if( !function_exists( 'memory_get_usage' ) ) {
27 # Old PHP or --enable-memory-limit not compiled in
28 function memory_get_usage() {
35 var $mStack = array(), $mWorkStack = array(), $mCollated = array();
36 var $mCalls = array(), $mTotals = array();
40 $this->mProfileStack = array();
41 $this->mWorkStack = array();
42 $this->mCollated = array();
46 function profileIn( $functionname )
48 global $wgDebugFunctionEntry;
49 if ( $wgDebugFunctionEntry && function_exists( "wfDebug" ) ) {
50 wfDebug( str_repeat( " ", count( $this->mWorkStack
) ) . "Entering $functionname\n" );
52 array_push( $this->mWorkStack
, array($functionname, count( $this->mWorkStack
), microtime(), memory_get_usage() ) );
55 function profileOut( $functionname )
57 $memory = memory_get_usage();
58 global $wgDebugProfiling, $wgDebugFunctionEntry;
60 if ( $wgDebugFunctionEntry && function_exists( "wfDebug" ) ) {
61 wfDebug( str_repeat( " ", count( $this->mWorkStack
) - 1 ) . "Exiting $functionname\n" );
64 $bit = array_pop( $this->mWorkStack
);
67 wfDebug( "Profiling error, !\$bit: $functionname\n" );
69 if ( $wgDebugProfiling ) {
70 if ( $functionname == "close" ) {
71 wfDebug( "Profile section ended by close(): {$bit[0]}\n" );
72 } elseif ( $bit[0] != $functionname ) {
73 wfDebug( "Profiling error: in({$bit[0]}), out($functionname)\n" );
76 array_push( $bit, microtime() );
77 array_push( $bit, $memory );
78 array_push( $this->mStack
, $bit );
84 while ( count( $this->mWorkStack
) ) {
85 $this->profileOut( "close" );
91 global $wgDebugFunctionEntry;
92 $wgDebugFunctionEntry = false;
94 if( !count( $this->mStack
) ) {
95 return "No profiling output\n";
99 $format = "%-" . ($width - 34) . "s %6d %6.3f %6.3f %6.3f%% %6d\n";
100 $titleFormat = "%-" . ($width - 34) . "s %9s %9s %9s %9s %6s\n";
101 $prof = "\nProfiling data\n";
102 $prof .= sprintf( $titleFormat, "Name", "Calls", "Total", "Each", "%", "Mem" );
103 $this->mCollated
= array();
104 $this->mCalls
= array();
106 # Estimate profiling overhead
107 $profileCount = count( $this->mStack
);
108 wfProfileIn( "-overhead-total" );
109 for ($i=0; $i<$profileCount ; $i++
) {
110 wfProfileIn( "-overhead-internal" );
111 wfProfileOut( "-overhead-internal" );
113 wfProfileOut( "-overhead-total" );
116 foreach ( $this->mStack
as $entry ) {
118 $thislevel = $entry[1];
119 $start = explode( " ", $entry[2]);
120 $start = (float)$start[0] +
(float)$start[1];
121 $end = explode( " ", $entry[4]);
122 $end = (float)$end[0] +
(float)$end[1];
123 $elapsed = $end - $start;
125 $memory = $entry[5] - $entry[3];
127 if ( !array_key_exists( $fname, $this->mCollated
) ) {
128 $this->mCollated
[$fname] = 0;
129 $this->mCalls
[$fname] = 0;
132 $this->mCollated
[$fname] +
= $elapsed;
133 $this->mCalls
[$fname] ++
;
134 $this->mMemory
[$fname] +
= $memory;
137 $total = @$this->mCollated
["-total"];
138 $overhead = $this->mCollated
["-overhead-internal"] / $profileCount;
139 $this->mCalls
["-overhead-total"] = $profileCount;
142 foreach ( $this->mCollated
as $fname => $elapsed ) {
143 $calls = $this->mCalls
[$fname];
144 # Adjust for overhead
145 if ( $fname[0] != "-" ) {
146 $elapsed -= $overhead * $calls;
149 $percent = $total ?
100. * $elapsed / $total : 0;
150 $memory = $this->mMemory
[$fname];
151 $prof .= sprintf( $format, $fname, $calls, (float)($elapsed * 1000),
152 (float)($elapsed * 1000) / $calls, $percent, $memory );
154 global $wgProfileToDatabase;
155 if( $wgProfileToDatabase ) {
156 Profiler
::logToDB( $fname, (float)($elapsed * 1000), $calls );
159 $prof .= "\nTotal: $total\n\n";
165 /* static */ function logToDB($name, $timeSum, $eventCount)
167 $dbw =& wfGetDB( DB_MASTER
);
168 $profiling = $dbw->tableName( 'profiling' );
170 $name = $dbw->strencode( $name );
171 $sql = "UPDATE $profiling ".
172 "SET pf_count=pf_count+{$eventCount}, ".
173 "pf_time=pf_time + {$timeSum} ".
174 "WHERE pf_name='{$name}'";
177 $rc = $dbw->affectedRows();
179 $sql = "INSERT IGNORE INTO $profiling (pf_name,pf_count,pf_time) ".
180 "VALUES ('{$name}', {$eventCount}, {$timeSum}) ";
181 $dbw->query($sql , DB_MASTER
);
183 // When we upgrade to mysql 4.1, the insert+update
184 // can be merged into just a insert with this construct added:
185 // "ON DUPLICATE KEY UPDATE ".
186 // "pf_count=pf_count + VALUES(pf_count), ".
187 // "pf_time=pf_time + VALUES(pf_time)";
193 $wgProfiler = new Profiler();
194 $wgProfiler->profileIn( "-total" );