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 | private $period; |
32 | |
33 | /** |
34 | * @param array $params Associative array of parameters: |
35 | * - period: The sampling period |
36 | * - maxDepth: The maximum stack depth collected |
37 | * - cpuProfiler: A pre-started ExcimerProfiler instance for CPU |
38 | * profiling of the entire request including configuration. |
39 | * - realProfiler: A pre-started ExcimerProfiler instance for wall |
40 | * clock profiling of the entire request. |
41 | */ |
42 | public function __construct( array $params = [] ) { |
43 | parent::__construct( $params ); |
44 | |
45 | $this->period = $params['period'] ?? 0.01; |
46 | $maxDepth = $params['maxDepth'] ?? 100; |
47 | |
48 | if ( isset( $params['cpuProfiler'] ) ) { |
49 | $this->cpuProf = $params['cpuProfiler']; |
50 | } else { |
51 | $this->cpuProf = new ExcimerProfiler; |
52 | $this->cpuProf->setEventType( EXCIMER_CPU ); |
53 | $this->cpuProf->setPeriod( $this->period ); |
54 | $this->cpuProf->setMaxDepth( $maxDepth ); |
55 | $this->cpuProf->start(); |
56 | } |
57 | |
58 | if ( isset( $params['realProfiler'] ) ) { |
59 | $this->realProf = $params['realProfiler']; |
60 | } else { |
61 | $this->realProf = new ExcimerProfiler; |
62 | $this->realProf->setEventType( EXCIMER_REAL ); |
63 | $this->realProf->setPeriod( $this->period ); |
64 | $this->realProf->setMaxDepth( $maxDepth ); |
65 | $this->realProf->start(); |
66 | } |
67 | } |
68 | |
69 | public function scopedProfileIn( $section ) { |
70 | } |
71 | |
72 | public function close() { |
73 | $this->cpuProf->stop(); |
74 | $this->realProf->stop(); |
75 | } |
76 | |
77 | public function getFunctionStats() { |
78 | $this->close(); |
79 | $cpuStats = $this->cpuProf->getLog()->aggregateByFunction(); |
80 | '@phan-var array $cpuStats'; |
81 | $realStats = $this->realProf->getLog()->aggregateByFunction(); |
82 | '@phan-var array $realStats'; |
83 | $allNames = array_keys( $realStats + $cpuStats ); |
84 | $cpuSamples = $this->cpuProf->getLog()->getEventCount(); |
85 | $realSamples = $this->realProf->getLog()->getEventCount(); |
86 | |
87 | $resultStats = [ [ |
88 | 'name' => '-total', |
89 | 'calls' => 1, |
90 | 'memory' => 0, |
91 | '%memory' => 0, |
92 | 'min_real' => 0, |
93 | 'max_real' => 0, |
94 | 'cpu' => $cpuSamples * $this->period * 1000, |
95 | '%cpu' => 100, |
96 | 'real' => $realSamples * $this->period * 1000, |
97 | '%real' => 100, |
98 | ] ]; |
99 | |
100 | foreach ( $allNames as $funcName ) { |
101 | $cpuEntry = $cpuStats[$funcName] ?? false; |
102 | $realEntry = $realStats[$funcName] ?? false; |
103 | $resultEntry = [ |
104 | 'name' => $funcName, |
105 | 'calls' => 0, |
106 | 'memory' => 0, |
107 | '%memory' => 0, |
108 | 'min_real' => 0, |
109 | 'max_real' => 0, |
110 | ]; |
111 | |
112 | if ( $cpuEntry ) { |
113 | $resultEntry['cpu'] = $cpuEntry['inclusive'] * $this->period * 1000; |
114 | $resultEntry['%cpu'] = $cpuEntry['inclusive'] / $cpuSamples * 100; |
115 | } else { |
116 | $resultEntry['cpu'] = 0; |
117 | $resultEntry['%cpu'] = 0; |
118 | } |
119 | if ( $realEntry ) { |
120 | $resultEntry['real'] = $realEntry['inclusive'] * $this->period * 1000; |
121 | $resultEntry['%real'] = $realEntry['inclusive'] / $realSamples * 100; |
122 | } else { |
123 | $resultEntry['real'] = 0; |
124 | $resultEntry['%real'] = 0; |
125 | } |
126 | |
127 | $resultStats[] = $resultEntry; |
128 | } |
129 | return $resultStats; |
130 | } |
131 | |
132 | public function getOutput() { |
133 | $this->close(); |
134 | $cpuLog = $this->cpuProf->getLog(); |
135 | $realLog = $this->realProf->getLog(); |
136 | $cpuStats = $cpuLog->aggregateByFunction(); |
137 | '@phan-var array $cpuStats'; |
138 | $realStats = $realLog->aggregateByFunction(); |
139 | '@phan-var array $realStats'; |
140 | $allNames = array_keys( $cpuStats + $realStats ); |
141 | $cpuSamples = $cpuLog->getEventCount(); |
142 | $realSamples = $realLog->getEventCount(); |
143 | |
144 | $result = ''; |
145 | |
146 | $titleFormat = "%-70s %10s %11s %10s %11s %10s %11s %10s %11s\n"; |
147 | $statsFormat = "%-70s %10d %10.1f%% %10d %10.1f%% %10d %10.1f%% %10d %10.1f%%\n"; |
148 | $result .= sprintf( $titleFormat, |
149 | 'Name', |
150 | 'CPU incl', 'CPU incl%', 'CPU self', 'CPU self%', |
151 | 'Real incl', 'Real incl%', 'Real self', 'Real self%' |
152 | ); |
153 | |
154 | foreach ( $allNames as $funcName ) { |
155 | $realEntry = $realStats[$funcName] ?? false; |
156 | $cpuEntry = $cpuStats[$funcName] ?? false; |
157 | $realIncl = $realEntry ? $realEntry['inclusive'] : 0; |
158 | $realSelf = $realEntry ? $realEntry['self'] : 0; |
159 | $cpuIncl = $cpuEntry ? $cpuEntry['inclusive'] : 0; |
160 | $cpuSelf = $cpuEntry ? $cpuEntry['self'] : 0; |
161 | $result .= sprintf( $statsFormat, |
162 | $funcName, |
163 | $cpuIncl * $this->period * 1000, |
164 | $cpuIncl == 0 ? 0 : $cpuIncl / $cpuSamples * 100, |
165 | $cpuSelf * $this->period * 1000, |
166 | $cpuSelf == 0 ? 0 : $cpuSelf / $cpuSamples * 100, |
167 | $realIncl * $this->period * 1000, |
168 | $realIncl == 0 ? 0 : $realIncl / $realSamples * 100, |
169 | $realSelf * $this->period * 1000, |
170 | $realSelf == 0 ? 0 : $realSelf / $realSamples * 100 |
171 | ); |
172 | } |
173 | |
174 | return $result; |
175 | } |
176 | } |