21 use Wikimedia\RunningStat;
65 $this->config = array_merge( [
70 $this->hieraData = $this->
pruneData( $data );
114 return array_pad( explode(
'==>', $key, 2 ), -2,
null );
125 if ( !$this->config[
'include'] ) {
129 $want = array_fill_keys( $this->config[
'include'],
true );
130 $want[
'main()'] =
true;
133 foreach ( $data as $key => $stats ) {
135 if ( isset( $want[$parent] ) || isset( $want[$child] ) ) {
136 $keep[$key] = $stats;
161 if ( $this->inclusive ===
null ) {
162 $main = $this->hieraData[
'main()'];
163 $hasCpu = isset( $main[
'cpu'] );
164 $hasMu = isset( $main[
'mu'] );
165 $hasAlloc = isset( $main[
'alloc'] );
167 $this->inclusive = [];
168 foreach ( $this->hieraData as $key => $stats ) {
170 if ( !isset( $this->inclusive[$child] ) ) {
171 $this->inclusive[$child] = [
173 'wt' =>
new RunningStat(),
176 $this->inclusive[$child][
'cpu'] =
new RunningStat();
179 $this->inclusive[$child][
'mu'] =
new RunningStat();
180 $this->inclusive[$child][
'pmu'] =
new RunningStat();
183 $this->inclusive[$child][
'alloc'] =
new RunningStat();
184 $this->inclusive[$child][
'free'] =
new RunningStat();
188 $this->inclusive[$child][
'ct'] += $stats[
'ct'];
189 foreach ( $stats as $stat => $value ) {
190 if ( $stat ===
'ct' ) {
194 if ( !isset( $this->inclusive[$child][$stat] ) ) {
199 for ( $i = 0; $i < $stats[
'ct']; $i++ ) {
200 $this->inclusive[$child][$stat]->addObservation(
201 $value / $stats[
'ct']
209 foreach ( $this->inclusive as $func => $stats ) {
210 foreach ( $stats as $name => $value ) {
211 if ( $value instanceof RunningStat ) {
212 $total = $value->getMean() * $value->getCount();
213 $percent = ( isset( $main[$name] ) && $main[$name] )
214 ? 100 * $total / $main[$name]
216 $this->inclusive[$func][$name] = [
218 'min' => $value->min,
219 'mean' => $value->getMean(),
220 'max' => $value->max,
221 'variance' => $value->m2,
222 'percent' => $percent,
228 uasort( $this->inclusive, self::makeSortFunction(
229 $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 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;