block/unblock log; split off profiling into Profiling.php and broke it (turn it off...
[lhc/web/wiklou.git] / includes / Profiling.php
1 <?
2 # This file is only included if profiling is enabled
3 $wgDebugProfiling = true;
4
5 function wfProfileIn( $functionname )
6 {
7 global $wgProfiler;
8 $wgProfiler->profileIn( $functionname );
9 }
10
11 function wfProfileOut( $functionname = "missing" )
12 {
13 global $wgProfiler;
14 $wgProfiler->profileOut( $functionname );
15 }
16
17 function wfGetProfilingOutput( $start, $elapsed ) {
18 global $wgProfiler;
19 return $wgProfiler->getOutput( $start, $elapsed );
20 }
21
22 function wfProfileClose()
23 {
24 global $wgProfiler;
25 $wgProfiler->close();
26 }
27
28 class Profiler
29 {
30 var $mStack = array(), $mWorkStack = array(), $mCollated = array();
31 var $mCalls = array(), $mTotals = array();
32 /*
33 function Profiler()
34 {
35 $this->mProfileStack = array();
36 $this->mWorkStack = array();
37 $this->mCollated = array();
38 }
39 */
40
41 function profileIn( $functionname )
42 {
43 array_push( $this->mWorkStack, array($functionname, count( $this->mWorkStack ), microtime() ) );
44 }
45
46 function profileOut( $functionname)
47 {
48 global $wgDebugProfiling;
49 $bit = array_pop( $this->mWorkStack );
50
51 if ( $wgDebugProfiling ) {
52 if ( $functionname == "close" ) {
53 wfDebug( "Profile section ended by close(): {$bit[0]}\n" );
54 } elseif ( $bit[0] != $functionname ) {
55 wfDebug( "Profiling error: in({$bit[0]}), out($functionname)\n" );
56 }
57 }
58 array_push( $bit, microtime() );
59 array_push( $this->mStack, $bit );
60 }
61
62 function close()
63 {
64 while ( count( $this->mWorkStack ) ) {
65 $this->profileOut( "close" );
66 }
67 }
68
69
70 function getOutput( $scriptStart, $scriptElapsed )
71 {
72 set_time_limit( 0 );
73 $width = 80;
74 $format = "%-39s %6.2f / %6.2f = %6.2f %6.2f%%\n";
75 $prof = "";
76 if( !count( $this->mStack ) ) {
77 return "No profiling output\n";
78 }
79 $this->mCollated = array();
80
81 $top = $this->doLevel( 0, true );
82 $this->merge( "WIKI.PHTML", $top, $scriptElapsed );
83 $this->mCollated = array_reverse( $this->mCollated, true );
84 /*
85 # Calculate totals
86 foreach ( $this->mCollated as $f1 => $f1data ) {
87 $total = 0;
88 foreach ( $f1data as $f2 => $t ) {
89 $total += $t;
90 }
91 $this->mCollated[$f1][0] = $total;
92 }
93 */
94 # Output
95 foreach ( $this->mCollated as $f1 => $f1data ) {
96 $prof .= "\n" . str_repeat( "-", $width ) . "\n";
97 $t = $this->mTotals[$f1] * 1000;
98 $calls = $this->mCalls[$f1];
99 if ( $calls == 0 ) {
100 $calls = 1;
101 }
102 $each = $t / $calls;
103 $percent = $this->mTotals[$f1] / $scriptElapsed * 100;
104 $prof .= sprintf( $format, "| $f1", $t, $calls, $each, $percent );
105 $prof .= str_repeat( "-", $width ) . "\n";
106 foreach ( $f1data as $f2 => $t ) {
107 $percent = $t / $this->mTotals[$f1] * 100;
108 $t *= 1000;
109 $calls = $this->mCalls[$f1];
110 if ( $calls == 0 ) {
111 $calls = 1;
112 }
113 $each = $t / $calls;
114 $percent = $this->mTotals[$f1] / $scriptElapsed * 100;
115 $prof .= sprintf( $format, $f2, $t, $calls, $each, $percent );
116 }
117 }
118 $prof .= str_repeat( "-", $width ) . "\n";
119 return $prof;
120 }
121
122
123 function doLevel( $p, $fTop )
124 {
125 $level = false;
126 $getOut = false;
127 $hotArray = false;
128 $tempArray = array();
129 do {
130 $fname = $this->mStack[$p][0];
131 $thislevel = $this->mStack[$p][1];
132 $start = (float)$this->mStack[$p][2] + (float)$this->mStack[$p][3];
133 $end = (float)$this->mStack[$p][4] + (float)$this->mStack[$p][5];
134 $elapsed = $end - $start;
135 if ( $hotArray !== false ) {
136 # Just dropped down a level
137 # Therefore this entry is the parent of $hotArray
138 $this->merge( $fname, $hotArray, $elapsed );
139 $hotArray = false;
140 }
141
142 if ( $level === false ) {
143 $level = $thislevel;
144 }
145
146 if ( $thislevel == $level ) {
147 $tempArray[$fname] += $elapsed;
148 #$this->mTotals[$fname] += elapsed;
149 $this->mCalls[$fname] ++;
150 } elseif ($thislevel > $level ) {
151 $hotArray = $this->doLevel( $p, false );
152 } else {
153 $getOut = true;
154 }
155
156 # Special case: top of hierarchy
157 # File starts with lvl 1 entry, then drops back to lvl 0
158 if ( $fTop && $getOut ) {
159 $hotArray = $tempArray;
160 $getOut = false;
161 }
162
163 $p++;
164 } while ( !$getOut && $p < count( $this->mStack ) );
165 return $tempArray;
166 }
167
168 function merge( $f1, $a, $parentTime )
169 {
170 foreach ( $a as $f2 => $elapsed ) {
171 $this->mCollated[$f1][$f2] += $elapsed;
172 }
173 $this->mTotals[$f1] += $parentTime;
174 }
175 }
176
177 $wgProfiler = new Profiler();
178
179 ?>