21use Wikimedia\RunningStat;
64 $this->config = array_merge( [
69 $this->hieraData = $this->
pruneData( $data );
113 return array_pad( explode(
'==>', $key, 2 ), -2,
null );
124 if ( !$this->config[
'include'] ) {
128 $want = array_fill_keys( $this->config[
'include'],
true );
129 $want[
'main()'] =
true;
132 foreach ( $data as $key => $stats ) {
134 if ( isset( $want[$parent] ) || isset( $want[$child] ) ) {
135 $keep[$key] = $stats;
160 if ( $this->inclusive ===
null ) {
161 $main = $this->hieraData[
'main()'];
162 $hasCpu = isset( $main[
'cpu'] );
163 $hasMu = isset( $main[
'mu'] );
164 $hasAlloc = isset( $main[
'alloc'] );
167 foreach ( $this->hieraData as $key => $stats ) {
172 'wt' =>
new RunningStat(),
175 $inclusive[$child][
'cpu'] =
new RunningStat();
179 $inclusive[$child][
'pmu'] =
new RunningStat();
182 $inclusive[$child][
'alloc'] =
new RunningStat();
183 $inclusive[$child][
'free'] =
new RunningStat();
188 foreach ( $stats as $stat => $value ) {
189 if ( $stat ===
'ct' ) {
198 for ( $i = 0; $i < $stats[
'ct']; $i++ ) {
200 $value / $stats[
'ct']
209 foreach ( $stats as $name => $value ) {
210 if ( $value instanceof RunningStat ) {
211 $total = $value->getMean() * $value->getCount();
212 $percent = ( isset( $main[$name] ) && $main[$name] )
213 ? 100 * $total / $main[$name]
217 'min' => $value->min,
218 'mean' => $value->getMean(),
219 'max' => $value->max,
220 'variance' => $value->m2,
221 'percent' => $percent,
228 $this->config[
'sort'],
'total'
247 if ( $this->complete ===
null ) {
251 foreach ( $this->complete as $func => $stats ) {
252 foreach ( $stats as $stat => $value ) {
253 if ( $stat ===
'ct' ) {
257 $this->complete[$func][$stat][
'exclusive'] = $value[
'total'];
260 $this->complete[$func][
'calls'] = [];
261 $this->complete[$func][
'subcalls'] = [];
264 foreach ( $this->hieraData as $key => $stats ) {
266 if ( $parent !==
null ) {
268 $this->complete[$child][
'calls'][$parent] = $stats;
269 $this->complete[$parent][
'subcalls'][$child] = $stats;
272 if ( isset( $this->complete[$parent] ) ) {
274 foreach ( $stats as $stat => $value ) {
275 if ( $stat ===
'ct' ) {
279 if ( !isset( $this->complete[$parent][$stat] ) ) {
284 $this->complete[$parent][$stat][
'exclusive'] -= $value;
289 uasort( $this->complete, self::makeSortFunction(
290 $this->config[
'sort'],
'exclusive'
305 if ( isset( $edges[$function][
'calls'] ) ) {
306 return array_keys( $edges[$function][
'calls'] );
321 if ( isset( $edges[$function][
'subcalls'] ) ) {
322 return array_keys( $edges[$function][
'subcalls'] );
337 $func => $this->hieraData[$func],
343 foreach ( $callees as $callee ) {
344 $call =
"{$func}==>{$callee}";
345 if ( $maxCall ===
null ||
346 $this->hieraData[$call][$metric] >
347 $this->hieraData[$maxCall][$metric]
349 $maxCallee = $callee;
353 if ( $maxCall !==
null ) {
354 $path[$maxCall] = $this->hieraData[$maxCall];
370 return static function ( $a, $b ) use ( $key, $sub ) {
371 if ( isset( $a[$key] ) && isset( $b[$key] ) ) {
374 $valA = is_array( $a[$key] ) ? $a[$key][$sub] : $a[$key];
375 $valB = is_array( $b[$key] ) ? $b[$key][$sub] : $b[$key];
376 return $valB <=> $valA;
379 return isset( $a[$key] ) ? -1 : 1;
Convenience class for working with XHProf profiling data https://github.com/phacility/xhprof.
getCriticalPath( $metric='wt')
Find the critical path for the given metric.
array[] $complete
Per-function inclusive and exclusive data.
pruneData( $data)
Remove data for functions that are not included in the 'include' configuration array.
getInclusiveMetrics()
Get the inclusive metrics for each function call.
array[][] $inclusive
Per-function inclusive data.
static makeSortFunction( $key, $sub)
Make a closure to use as a sort function.
getCallees( $function)
Get a list of all callees from a given function.
getRawData()
Get raw data collected by xhprof.
__construct(array $data, array $config=[])
Configuration data can contain:
array[] $hieraData
Hierarchical profiling data returned by xhprof.
getCallers( $function)
Get a list of all callers of a given function.
static splitKey( $key)
Convert an xhprof data key into an array of ['parent', 'child'] function names.
getCompleteMetrics()
Get the inclusive and exclusive metrics for each function call.