Remove per-template profiling
[lhc/web/wiklou.git] / includes / profiler / Profiler.php
1 <?php
2 /**
3 * Base class for profiling.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Profiler
22 * @defgroup Profiler Profiler
23 */
24
25 /**
26 * Profiler base class that defines the interface and some trivial
27 * functionality
28 *
29 * @ingroup Profiler
30 */
31 abstract class Profiler {
32 /** @var string|bool Profiler ID for bucketing data */
33 protected $profileID = false;
34 /** @var bool Whether MediaWiki is in a SkinTemplate output context */
35 protected $templated = false;
36
37 /** @var TransactionProfiler */
38 protected $trxProfiler;
39
40 // @codingStandardsIgnoreStart PSR2.Classes.PropertyDeclaration.Underscore
41 /** @var Profiler Do not call this outside Profiler and ProfileSection */
42 public static $__instance = null;
43 // @codingStandardsIgnoreEnd
44
45 /**
46 * @param array $params
47 */
48 public function __construct( array $params ) {
49 if ( isset( $params['profileID'] ) ) {
50 $this->profileID = $params['profileID'];
51 }
52 $this->trxProfiler = new TransactionProfiler();
53 }
54
55 /**
56 * Singleton
57 * @return Profiler
58 */
59 final public static function instance() {
60 if ( self::$__instance === null ) {
61 global $wgProfiler;
62 if ( is_array( $wgProfiler ) ) {
63 if ( !isset( $wgProfiler['class'] ) ) {
64 $class = 'ProfilerStub';
65 } else {
66 $class = $wgProfiler['class'];
67 }
68 self::$__instance = new $class( $wgProfiler );
69 } else {
70 self::$__instance = new ProfilerStub( array() );
71 }
72 }
73 return self::$__instance;
74 }
75
76 /**
77 * Return whether this a stub profiler
78 *
79 * @return bool
80 */
81 abstract public function isStub();
82
83 /**
84 * @param string $id
85 */
86 public function setProfileID( $id ) {
87 $this->profileID = $id;
88 }
89
90 /**
91 * @return string
92 */
93 public function getProfileID() {
94 if ( $this->profileID === false ) {
95 return wfWikiID();
96 } else {
97 return $this->profileID;
98 }
99 }
100
101 /**
102 * Called by wfProfieIn()
103 *
104 * @param string $functionname
105 */
106 abstract public function profileIn( $functionname );
107
108 /**
109 * Called by wfProfieOut()
110 *
111 * @param string $functionname
112 */
113 abstract public function profileOut( $functionname );
114
115 /**
116 * @return TransactionProfiler
117 * @since 1.25
118 */
119 public function getTransactionProfiler() {
120 return $this->trxProfiler;
121 }
122
123 /**
124 * Close opened profiling sections
125 */
126 abstract public function close();
127
128 /**
129 * Log the data to some store or even the page output
130 */
131 abstract public function logData();
132
133 /**
134 * Mark this call as templated or not
135 *
136 * @param bool $t
137 */
138 public function setTemplated( $t ) {
139 $this->templated = $t;
140 }
141
142 /**
143 * Returns a profiling output to be stored in debug file
144 *
145 * @return string
146 */
147 abstract public function getOutput();
148
149 /**
150 * Get data for the debugging toolbar.
151 *
152 * @return array
153 */
154 abstract public function getRawData();
155
156 /**
157 * Get the initial time of the request, based either on $wgRequestTime or
158 * $wgRUstart. Will return null if not able to find data.
159 *
160 * @param string|bool $metric Metric to use, with the following possibilities:
161 * - user: User CPU time (without system calls)
162 * - cpu: Total CPU time (user and system calls)
163 * - wall (or any other string): elapsed time
164 * - false (default): will fall back to default metric
165 * @return float|null
166 */
167 protected function getTime( $metric = 'wall' ) {
168 if ( $metric === 'cpu' || $metric === 'user' ) {
169 $ru = wfGetRusage();
170 if ( !$ru ) {
171 return 0;
172 }
173 $time = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
174 if ( $metric === 'cpu' ) {
175 # This is the time of system calls, added to the user time
176 # it gives the total CPU time
177 $time += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
178 }
179 return $time;
180 } else {
181 return microtime( true );
182 }
183 }
184
185 /**
186 * Get the initial time of the request, based either on $wgRequestTime or
187 * $wgRUstart. Will return null if not able to find data.
188 *
189 * @param string|bool $metric Metric to use, with the following possibilities:
190 * - user: User CPU time (without system calls)
191 * - cpu: Total CPU time (user and system calls)
192 * - wall (or any other string): elapsed time
193 * - false (default): will fall back to default metric
194 * @return float|null
195 */
196 protected function getInitialTime( $metric = 'wall' ) {
197 global $wgRequestTime, $wgRUstart;
198
199 if ( $metric === 'cpu' || $metric === 'user' ) {
200 if ( !count( $wgRUstart ) ) {
201 return null;
202 }
203
204 $time = $wgRUstart['ru_utime.tv_sec'] + $wgRUstart['ru_utime.tv_usec'] / 1e6;
205 if ( $metric === 'cpu' ) {
206 # This is the time of system calls, added to the user time
207 # it gives the total CPU time
208 $time += $wgRUstart['ru_stime.tv_sec'] + $wgRUstart['ru_stime.tv_usec'] / 1e6;
209 }
210 return $time;
211 } else {
212 if ( empty( $wgRequestTime ) ) {
213 return null;
214 } else {
215 return $wgRequestTime;
216 }
217 }
218 }
219 }