3 class ProfilerExcimer
extends Profiler
{
4 /** @var ExcimerProfiler */
6 /** @var ExcimerProfiler */
11 * @param array $params Associative array of parameters:
12 * - period: The sampling period
13 * - maxDepth: The maximum stack depth collected
14 * - cpuProfiler: A pre-started ExcimerProfiler instance for CPU
15 * profiling of the entire request including configuration.
16 * - realProfiler: A pre-started ExcimerProfiler instance for wall
17 * clock profiling of the entire request.
19 public function __construct( array $params = [] ) {
20 parent
::__construct( $params );
22 $this->period
= $params['period'] ??
0.01;
23 $maxDepth = $params['maxDepth'] ??
100;
25 if ( isset( $params['cpuProfiler'] ) ) {
26 $this->cpuProf
= $params['cpuProfiler'];
28 $this->cpuProf
= new ExcimerProfiler
;
29 $this->cpuProf
->setEventType( EXCIMER_CPU
);
30 $this->cpuProf
->setPeriod( $this->period
);
31 $this->cpuProf
->setMaxDepth( $maxDepth );
32 $this->cpuProf
->start();
35 if ( isset( $params['realProfiler'] ) ) {
36 $this->realProf
= $params['realProfiler'];
38 $this->realProf
= new ExcimerProfiler
;
39 $this->realProf
->setEventType( EXCIMER_REAL
);
40 $this->realProf
->setPeriod( $this->period
);
41 $this->realProf
->setMaxDepth( $maxDepth );
42 $this->realProf
->start();
46 public function scopedProfileIn( $section ) {
49 public function close() {
50 $this->cpuProf
->stop();
51 $this->realProf
->stop();
54 public function getFunctionStats() {
56 $cpuStats = $this->cpuProf
->getLog()->aggregateByFunction();
57 $realStats = $this->realProf
->getLog()->aggregateByFunction();
58 $allNames = array_keys( $realStats +
$cpuStats );
59 $cpuSamples = $this->cpuProf
->getLog()->getEventCount();
60 $realSamples = $this->realProf
->getLog()->getEventCount();
69 'cpu' => $cpuSamples * $this->period
* 1000,
71 'real' => $realSamples * $this->period
* 1000,
75 foreach ( $allNames as $funcName ) {
76 $cpuEntry = $cpuStats[$funcName] ??
false;
77 $realEntry = $realStats[$funcName] ??
false;
88 $resultEntry['cpu'] = $cpuEntry['inclusive'] * $this->period
* 1000;
89 $resultEntry['%cpu'] = $cpuEntry['inclusive'] / $cpuSamples * 100;
91 $resultEntry['cpu'] = 0;
92 $resultEntry['%cpu'] = 0;
95 $resultEntry['real'] = $realEntry['inclusive'] * $this->period
* 1000;
96 $resultEntry['%real'] = $realEntry['inclusive'] / $realSamples * 100;
98 $resultEntry['real'] = 0;
99 $resultEntry['%real'] = 0;
102 $resultStats[] = $resultEntry;
107 public function getOutput() {
109 $cpuLog = $this->cpuProf
->getLog();
110 $realLog = $this->realProf
->getLog();
111 $cpuStats = $cpuLog->aggregateByFunction();
112 $realStats = $realLog->aggregateByFunction();
113 $allNames = array_keys( $cpuStats +
$realStats );
114 $cpuSamples = $cpuLog->getEventCount();
115 $realSamples = $realLog->getEventCount();
119 $titleFormat = "%-70s %10s %11s %10s %11s %10s %11s %10s %11s\n";
120 $statsFormat = "%-70s %10d %10.1f%% %10d %10.1f%% %10d %10.1f%% %10d %10.1f%%\n";
121 $result .= sprintf( $titleFormat,
123 'CPU incl', 'CPU incl%', 'CPU self', 'CPU self%',
124 'Real incl', 'Real incl%', 'Real self', 'Real self%'
127 foreach ( $allNames as $funcName ) {
128 $realEntry = $realStats[$funcName] ??
false;
129 $cpuEntry = $cpuStats[$funcName] ??
false;
130 $realIncl = $realEntry ?
$realEntry['inclusive'] : 0;
131 $realSelf = $realEntry ?
$realEntry['self'] : 0;
132 $cpuIncl = $cpuEntry ?
$cpuEntry['inclusive'] : 0;
133 $cpuSelf = $cpuEntry ?
$cpuEntry['self'] : 0;
134 $result .= sprintf( $statsFormat,
136 $cpuIncl * $this->period
* 1000,
137 $cpuIncl == 0 ?
0 : $cpuIncl / $cpuSamples * 100,
138 $cpuSelf * $this->period
* 1000,
139 $cpuSelf == 0 ?
0 : $cpuSelf / $cpuSamples * 100,
140 $realIncl * $this->period
* 1000,
141 $realIncl == 0 ?
0 : $realIncl / $realSamples * 100,
142 $realSelf * $this->period
* 1000,
143 $realSelf == 0 ?
0 : $realSelf / $realSamples * 100