MediaWiki
REL1_23
|
00001 <?php 00035 class ProfilerMwprof extends Profiler { 00036 00037 // Message types 00038 00039 const TYPE_SINGLE = 1; 00040 const TYPE_RUNNING = 2; 00041 00051 public function isPersistent() { 00052 return true; 00053 } 00054 00063 public function profileIn( $inName ) { 00064 $this->mWorkStack[] = array( $inName, count( $this->mWorkStack ), 00065 $this->getTime(), $this->getTime( 'cpu' ) ); 00066 } 00067 00075 public function getFunctionReport() { 00076 return ''; 00077 } 00078 00087 public function profileOut( $outName ) { 00088 list( $inName, $inCount, $inWall, $inCpu ) = array_pop( $this->mWorkStack ); 00089 00090 // Check for unbalanced profileIn / profileOut calls. 00091 // Bad entries are logged but not sent. 00092 if ( $inName !== $outName ) { 00093 $this->debugGroup( 'ProfilerUnbalanced', json_encode( array( $inName, $outName ) ) ); 00094 return; 00095 } 00096 00097 $elapsedCpu = $this->getTime( 'cpu' ) - $inCpu; 00098 $elapsedWall = $this->getTime() - $inWall; 00099 $this->updateEntry( $outName, $elapsedCpu, $elapsedWall ); 00100 $this->updateTrxProfiling( $outName, $elapsedWall ); 00101 } 00102 00110 public function updateEntry( $name, $elapsedCpu, $elapsedWall ) { 00111 // If this is the first measurement for this entry, store plain values. 00112 // Many profiled functions will only be called once per request. 00113 if ( !isset( $this->mCollated[$name] ) ) { 00114 $this->mCollated[$name] = array( 00115 'cpu' => $elapsedCpu, 00116 'wall' => $elapsedWall, 00117 'count' => 1, 00118 ); 00119 return; 00120 } 00121 00122 $entry = &$this->mCollated[$name]; 00123 00124 // If it's the second measurement, convert the plain values to 00125 // RunningStat instances, so we can push the incoming values on top. 00126 if ( $entry['count'] === 1 ) { 00127 $cpu = new RunningStat(); 00128 $cpu->push( $entry['cpu'] ); 00129 $entry['cpu'] = $cpu; 00130 00131 $wall = new RunningStat(); 00132 $wall->push( $entry['wall'] ); 00133 $entry['wall'] = $wall; 00134 } 00135 00136 $entry['count']++; 00137 $entry['cpu']->push( $elapsedCpu ); 00138 $entry['wall']->push( $elapsedWall ); 00139 } 00140 00149 public function logData() { 00150 global $wgUDPProfilerHost, $wgUDPProfilerPort; 00151 00152 $this->close(); 00153 00154 $sock = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP ); 00155 socket_connect( $sock, $wgUDPProfilerHost, $wgUDPProfilerPort ); 00156 $bufferLength = 0; 00157 $buffer = ''; 00158 foreach ( $this->mCollated as $name => $entry ) { 00159 $count = $entry['count']; 00160 $cpu = $entry['cpu']; 00161 $wall = $entry['wall']; 00162 00163 if ( $count === 1 ) { 00164 $data = array( self::TYPE_SINGLE, $name, $cpu, $wall ); 00165 } else { 00166 $data = array( self::TYPE_RUNNING, $name, $count, 00167 $cpu->m1, $cpu->m2, $cpu->min, $cpu->max, 00168 $wall->m1, $wall->m2, $wall->min, $wall->max ); 00169 } 00170 00171 $encoded = MWMessagePack::pack( $data ); 00172 $length = strlen( $encoded ); 00173 00174 // If adding this entry would cause the size of the buffer to 00175 // exceed the standard ethernet MTU size less the UDP header, 00176 // send all pending data and reset the buffer. Otherwise, continue 00177 // accumulating entries into the current buffer. 00178 if ( $length + $bufferLength > 1450 ) { 00179 socket_send( $sock, $buffer, $bufferLength, 0 ); 00180 $buffer = ''; 00181 $bufferLength = 0; 00182 } 00183 $buffer .= $encoded; 00184 $bufferLength += $length; 00185 } 00186 if ( $bufferLength !== 0 ) { 00187 socket_send( $sock, $buffer, $bufferLength, 0 ); 00188 } 00189 } 00190 }