Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProfilerExcimer
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 5
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 scopedProfileIn
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 close
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getFunctionStats
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
20
 getOutput
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
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 */
26class 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}