PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.6.8
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.6.8
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
code-profiler / lib / class-profiler.php

class-profiler.php in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.6.8, at lib/class-profiler.php

262 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 +=====================================================================+
4 | ____ _ ____ __ _ _ |
5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 | |
10 | (c) Jerome Bruandet ~ https://code-profiler.com/ |
11 +=====================================================================+
12 */
13
14 if (! defined('ABSPATH') ) { die('Forbidden'); }
15
16 // =====================================================================
17
18 class CodeProfiler_Profiler {
19
20 static $tick_list;
21 static $buffer;
22 static $metrics;
23 static $fh;
24 static $connections_list = [];
25 static $connections_start;
26 private $tmp_iostats;
27 private $tmp_summary;
28 private $tmp_diskio;
29 private $tmp_calls;
30
31 /**
32 * Initialize
33 */
34 public function __construct() {
35
36 $microtime = sanitize_file_name( $_REQUEST['CODE_PROFILER_ON'] );
37
38 $this->tmp_summary = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
39 CODE_PROFILER_TMP_SUMMARY_LOG;
40 $this->tmp_iostats = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
41 CODE_PROFILER_TMP_IOSTATS_LOG;
42 $this->tmp_calls = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
43 CODE_PROFILER_TMP_CALLS_LOG;
44 $this->tmp_diskio = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
45 CODE_PROFILER_TMP_DISKIO_LOG;
46 $this->tmp_connections = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
47 CODE_PROFILER_TMP_CONNECTIONS_LOG;
48
49 if ( function_exists('hrtime') ) {
50 // PHP >=7.3
51 self::$metrics = 'hrtime';
52 } else {
53 self::$metrics = 'microtime';
54 }
55
56 // Select theme (stylesheet::template)
57 if (! empty( $_SERVER['HTTP_THEME'] ) ) {
58
59 $theme = explode('::', $_SERVER['HTTP_THEME'] );
60 if (! empty( $theme[1] ) ) {
61 define('CODE_PROFILER_STYLESHEET', sanitize_file_name( $theme[0] ) );
62 define('CODE_PROFILER_TEMPLATE', sanitize_file_name( $theme[1] ) );
63
64 if ( is_file( WP_CONTENT_DIR .'/themes/'. CODE_PROFILER_STYLESHEET .'/style.css' ) ) {
65
66 add_filter('pre_option_template', function () {
67 return CODE_PROFILER_TEMPLATE;
68 }, 1000 );
69
70 add_filter('pre_option_stylesheet', function () {
71 return CODE_PROFILER_STYLESHEET;
72 }, 1000 );
73
74 code_profiler_log_debug(
75 sprintf(
76 esc_html__('Setting theme to %s', 'code-profiler'),
77 CODE_PROFILER_STYLESHEET
78 )
79 );
80 } else {
81 code_profiler_log_error(
82 sprintf(
83 esc_html__('Unable to switch theme, %s not found', 'code-profiler'),
84 CODE_PROFILER_STYLESHEET
85 )
86 );
87 }
88 }
89 }
90
91 $cp_options = get_option('code-profiler');
92 if ( empty( $cp_options['accuracy'] ) ) {
93 define('CODE_PROFILER_TICKS', 1 );
94 } else {
95 define('CODE_PROFILER_TICKS', (int) $cp_options['accuracy'] );
96 }
97 define('CODE_PROFILER_LENGTH', 17 + strlen( (string) CODE_PROFILER_TICKS ) );
98
99 if ( empty( $cp_options['buffer'] ) ||
100 ! preg_match('/^(?:[1-9]|10)$/', $cp_options['buffer'] ) ) {
101
102 $recommended = code_profiler_suggested_memory();
103 self::$buffer = (int) $recommended * 1000000;
104 } else {
105 self::$buffer = $cp_options['buffer'] * 1000000;
106 }
107 code_profiler_log_debug(
108 sprintf(
109 esc_html__('Setting size of memory buffer to %sMB', 'code-profiler'),
110 self::$buffer / 1000000
111 )
112 );
113
114 add_filter('pre_http_request', [ $this, 'pre_http_request'], 10000, 3 );
115 add_action('http_api_debug', [ $this, 'http_api_debug'], 10000, 5 );
116 register_shutdown_function( [ $this, 'code_profiler_shutdown'] );
117 code_profiler_log_debug(
118 esc_html__('Starting profiler', 'code-profiler')
119 );
120 require 'class-stream.php';
121
122 // Clear the temporary log because the buffer will be appended to it
123 if ( file_exists( $this->tmp_calls ) ) {
124 unlink( $this->tmp_calls );
125 }
126 self::$fh = fopen( $this->tmp_calls, 'wb');
127
128 CodeProfiler_Stream::start();
129 register_tick_function( array( $this, 'code_profiler_tick_handler') );
130 }
131
132 /**
133 * Save data and check for potential PHP errors.
134 */
135 public function code_profiler_shutdown() {
136
137 CodeProfiler_Stream::stop();
138
139 fclose( self::$fh );
140
141 $summary['memory'] = memory_get_peak_usage();
142 $summary['queries'] = get_num_queries() - 2;
143 $summary['precision'] = CODE_PROFILER_TICKS;
144 file_put_contents( $this->tmp_summary, json_encode( $summary ) );
145
146 // Catch potential error
147 $e = error_get_last();
148 if ( isset( $e['type'] ) && $e['type'] === E_ERROR ) {
149 $err = str_replace( "\n", ' - ', $e['message'] );
150 code_profiler_log_error( sprintf(
151 /* Translators: Error message, line number and script */
152 esc_html__('Error: E_ERROR (%s - line %s in %s)', 'code-profiler'),
153 esc_html( $err ),
154 (int) $e['line'],
155 esc_html( $e['file'] )
156 ));
157 }
158
159 $err_msg = esc_html__('Cannot open file for writting: %s', 'code-profiler');
160 $res = file_put_contents( $this->tmp_iostats, json_encode( CodeProfiler_Stream::$io_stats ) );
161 if ( $res === false ) {
162 $msg = sprintf( $err_msg, $this->tmp_iostats );
163 code_profiler_log_error( $msg );
164 }
165 $res = file_put_contents( $this->tmp_calls, self::$tick_list, FILE_APPEND );
166 if ( $res === false ) {
167 $msg = sprintf( $err_msg, $this->tmp_calls );
168 code_profiler_log_error( $msg );
169 }
170 $res = file_put_contents(
171 $this->tmp_diskio, "read\t". CodeProfiler_Stream::$io_read ."\nwrite\t".
172 CodeProfiler_Stream::$io_write
173 );
174 if (! empty( self::$connections_list ) ) {
175 file_put_contents( $this->tmp_connections, json_encode( self::$connections_list) );
176 }
177 }
178
179 /**
180 * Our tick handler.
181 */
182 public function code_profiler_tick_handler() {
183
184 $start = $this->time();
185
186 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
187 if ( isset( $backtrace[1] ) ) {
188 $el = $backtrace[1];
189 } else {
190 $el = $backtrace[0];
191 }
192
193 if ( empty( $el['file'] ) ) {
194 if ( isset( $backtrace[0]['file'] ) ) {
195 $el['file'] = $backtrace[0]['file'];
196 } else {
197 return;
198 }
199 }
200
201 self::$tick_list .= "{$el['file']}\t";
202 if ( isset( $backtrace[0]['file'][0] ) ) {
203 self::$tick_list .= $backtrace[0]['file'];
204 } else {
205 self::$tick_list .= '-';
206 }
207 $backtrace = null;
208
209 // Buffer can grow *very* big hence we flush it every 10MB by default
210 if ( strlen( self::$tick_list ) > self::$buffer ) {
211 CodeProfiler_Stream::stop();
212 fwrite( self::$fh, self::$tick_list ."\t{$start}\t". $this->time() ."\n" );
213 CodeProfiler_Stream::start();
214 self::$tick_list = '';
215
216 } else {
217 self::$tick_list .="\t{$start}\t". $this->time() ."\n";
218 }
219 }
220
221
222 /**
223 * HTTP API request.
224 */
225 public function pre_http_request( $preempt, $r, $url ) {
226
227 if ( empty( $url ) ) {
228 return false;
229 }
230 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
231 self::$connections_start = $this->time();
232 self::$connections_list[ self::$connections_start ]['bt'] = $backtrace;
233 return false;
234 }
235
236
237 /**
238 * HTTP API response.
239 */
240 public function http_api_debug( $response, $context, $class, $parsed_args, $url ) {
241
242 self::$connections_list[ self::$connections_start ]['stop'] = $this->time();
243 }
244
245 /**
246 * Return time
247 */
248 private function time() {
249
250 if ( self::$metrics == 'hrtime') {
251 return hrtime( true );
252 } else {
253 return microtime( true );
254 }
255 }
256 }
257
258 new CodeProfiler_Profiler();
259
260 // =====================================================================
261 // EOF
262