Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 101 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
ProfilerExcimer | |
0.00% |
0 / 101 |
|
0.00% |
0 / 5 |
380 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
12 | |||
scopedProfileIn | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
close | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getFunctionStats | |
0.00% |
0 / 43 |
|
0.00% |
0 / 1 |
20 | |||
getOutput | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
110 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | /** |
22 | * @ingroup Profiler |
23 | * @since 1.33 |
24 | * @see $wgProfiler |
25 | */ |
26 | class ProfilerExcimer extends Profiler { |
27 | /** @var ExcimerProfiler */ |
28 | private $cpuProf; |
29 | /** @var ExcimerProfiler */ |
30 | private $realProf; |
31 | /** @var float */ |
32 | private $period; |
33 | |
34 | /** |
35 | * @param array $params Associative array of parameters: |
36 | * - period: The sampling period |
37 | * - maxDepth: The maximum stack depth collected |
38 | * - cpuProfiler: A pre-started ExcimerProfiler instance for CPU |
39 | * profiling of the entire request including configuration. |
40 | * - realProfiler: A pre-started ExcimerProfiler instance for wall |
41 | * clock profiling of the entire request. |
42 | */ |
43 | public function __construct( array $params = [] ) { |
44 | parent::__construct( $params ); |
45 | |
46 | $this->period = $params['period'] ?? 0.01; |
47 | $maxDepth = $params['maxDepth'] ?? 100; |
48 | |
49 | if ( isset( $params['cpuProfiler'] ) ) { |
50 | $this->cpuProf = $params['cpuProfiler']; |
51 | } else { |
52 | $this->cpuProf = new ExcimerProfiler; |
53 | $this->cpuProf->setEventType( EXCIMER_CPU ); |
54 | $this->cpuProf->setPeriod( $this->period ); |
55 | $this->cpuProf->setMaxDepth( $maxDepth ); |
56 | $this->cpuProf->start(); |
57 | } |
58 | |
59 | if ( isset( $params['realProfiler'] ) ) { |
60 | $this->realProf = $params['realProfiler']; |
61 | } else { |
62 | $this->realProf = new ExcimerProfiler; |
63 | $this->realProf->setEventType( EXCIMER_REAL ); |
64 | $this->realProf->setPeriod( $this->period ); |
65 | $this->realProf->setMaxDepth( $maxDepth ); |
66 | $this->realProf->start(); |
67 | } |
68 | } |
69 | |
70 | public function scopedProfileIn( $section ) { |
71 | } |
72 | |
73 | public function close() { |
74 | $this->cpuProf->stop(); |
75 | $this->realProf->stop(); |
76 | } |
77 | |
78 | public function getFunctionStats() { |
79 | $this->close(); |
80 | $cpuStats = $this->cpuProf->getLog()->aggregateByFunction(); |
81 | '@phan-var array $cpuStats'; |
82 | $realStats = $this->realProf->getLog()->aggregateByFunction(); |
83 | '@phan-var array $realStats'; |
84 | $allNames = array_keys( $realStats + $cpuStats ); |
85 | $cpuSamples = $this->cpuProf->getLog()->getEventCount(); |
86 | $realSamples = $this->realProf->getLog()->getEventCount(); |
87 | |
88 | $resultStats = [ [ |
89 | 'name' => '-total', |
90 | 'calls' => 1, |
91 | 'memory' => 0, |
92 | '%memory' => 0, |
93 | 'min_real' => 0, |
94 | 'max_real' => 0, |
95 | 'cpu' => $cpuSamples * $this->period * 1000, |
96 | '%cpu' => 100, |
97 | 'real' => $realSamples * $this->period * 1000, |
98 | '%real' => 100, |
99 | ] ]; |
100 | |
101 | foreach ( $allNames as $funcName ) { |
102 | $cpuEntry = $cpuStats[$funcName] ?? false; |
103 | $realEntry = $realStats[$funcName] ?? false; |
104 | $resultEntry = [ |
105 | 'name' => $funcName, |
106 | 'calls' => 0, |
107 | 'memory' => 0, |
108 | '%memory' => 0, |
109 | 'min_real' => 0, |
110 | 'max_real' => 0, |
111 | ]; |
112 | |
113 | if ( $cpuEntry ) { |
114 | $resultEntry['cpu'] = $cpuEntry['inclusive'] * $this->period * 1000; |
115 | $resultEntry['%cpu'] = $cpuEntry['inclusive'] / $cpuSamples * 100; |
116 | } else { |
117 | $resultEntry['cpu'] = 0; |
118 | $resultEntry['%cpu'] = 0; |
119 | } |
120 | if ( $realEntry ) { |
121 | $resultEntry['real'] = $realEntry['inclusive'] * $this->period * 1000; |
122 | $resultEntry['%real'] = $realEntry['inclusive'] / $realSamples * 100; |
123 | } else { |
124 | $resultEntry['real'] = 0; |
125 | $resultEntry['%real'] = 0; |
126 | } |
127 | |
128 | $resultStats[] = $resultEntry; |
129 | } |
130 | return $resultStats; |
131 | } |
132 | |
133 | public function getOutput() { |
134 | $this->close(); |
135 | $cpuLog = $this->cpuProf->getLog(); |
136 | $realLog = $this->realProf->getLog(); |
137 | $cpuStats = $cpuLog->aggregateByFunction(); |
138 | '@phan-var array $cpuStats'; |
139 | $realStats = $realLog->aggregateByFunction(); |
140 | '@phan-var array $realStats'; |
141 | $allNames = array_keys( $cpuStats + $realStats ); |
142 | $cpuSamples = $cpuLog->getEventCount(); |
143 | $realSamples = $realLog->getEventCount(); |
144 | |
145 | $result = ''; |
146 | |
147 | $titleFormat = "%-70s %10s %11s %10s %11s %10s %11s %10s %11s\n"; |
148 | $statsFormat = "%-70s %10d %10.1f%% %10d %10.1f%% %10d %10.1f%% %10d %10.1f%%\n"; |
149 | $result .= sprintf( $titleFormat, |
150 | 'Name', |
151 | 'CPU incl', 'CPU incl%', 'CPU self', 'CPU self%', |
152 | 'Real incl', 'Real incl%', 'Real self', 'Real self%' |
153 | ); |
154 | |
155 | foreach ( $allNames as $funcName ) { |
156 | $realEntry = $realStats[$funcName] ?? false; |
157 | $cpuEntry = $cpuStats[$funcName] ?? false; |
158 | $realIncl = $realEntry ? $realEntry['inclusive'] : 0; |
159 | $realSelf = $realEntry ? $realEntry['self'] : 0; |
160 | $cpuIncl = $cpuEntry ? $cpuEntry['inclusive'] : 0; |
161 | $cpuSelf = $cpuEntry ? $cpuEntry['self'] : 0; |
162 | $result .= sprintf( $statsFormat, |
163 | $funcName, |
164 | $cpuIncl * $this->period * 1000, |
165 | $cpuIncl == 0 ? 0 : $cpuIncl / $cpuSamples * 100, |
166 | $cpuSelf * $this->period * 1000, |
167 | $cpuSelf == 0 ? 0 : $cpuSelf / $cpuSamples * 100, |
168 | $realIncl * $this->period * 1000, |
169 | $realIncl == 0 ? 0 : $realIncl / $realSamples * 100, |
170 | $realSelf * $this->period * 1000, |
171 | $realSelf == 0 ? 0 : $realSelf / $realSamples * 100 |
172 | ); |
173 | } |
174 | |
175 | return $result; |
176 | } |
177 | } |