PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.9.6
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.9.6
1.9.6 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 All 41 releases
← All changes | lib/class-profiler.php +136 -29 1.5.51.9.6 View file →
@@ -6,9 +6,9 @@
6 6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 9 | |
10 - | (c) Jerome Bruandet ~ https://code-profiler.com/ |
10 + | (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ |
11 11 +=====================================================================+
12 12 */
13 13
14 14 if (! defined('ABSPATH') ) { die('Forbidden'); }
@@ -17,14 +17,20 @@
17 17
18 18 class CodeProfiler_Profiler {
19 19
20 20 static $tick_list;
21 - static $buffer = 10000000;
21 + static $buffer;
22 22 static $metrics;
23 + static $fh;
24 + static $connections_list = [];
25 + static $connections_start;
26 + static $exclusions = [];
23 27 private $tmp_iostats;
24 28 private $tmp_summary;
25 29 private $tmp_diskio;
26 - private $tmp_ticks;
30 + private $tmp_calls;
31 + private $tmp_connections;
32 + private $tmp_rerun;
27 33
28 34 /**
29 35 * Initialize
30 36 */
@@ -31,27 +37,63 @@
31 37 public function __construct() {
32 38
33 39 $microtime = sanitize_file_name( $_REQUEST['CODE_PROFILER_ON'] );
34 40
35 - $this->tmp_summary = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
36 - CODE_PROFILER_TMP_SUMMARY_LOG;
37 - $this->tmp_iostats = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
38 - CODE_PROFILER_TMP_IOSTATS_LOG;
39 - $this->tmp_ticks = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
40 - CODE_PROFILER_TMP_TICKS_LOG;
41 - $this->tmp_diskio = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
42 - CODE_PROFILER_TMP_DISKIO_LOG;
41 + $this->tmp_summary = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
42 + CODE_PROFILER_TMP_SUMMARY_LOG;
43 + $this->tmp_iostats = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
44 + CODE_PROFILER_TMP_IOSTATS_LOG;
45 + $this->tmp_calls = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
46 + CODE_PROFILER_TMP_CALLS_LOG;
47 + $this->tmp_diskio = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
48 + CODE_PROFILER_TMP_DISKIO_LOG;
49 + $this->tmp_connections = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
50 + CODE_PROFILER_TMP_CONNECTIONS_LOG;
51 + $this->tmp_rerun = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
52 + CODE_PROFILER_TMP_RERUN_LOG;
43 53
44 - // Clear the temporary log because the buffer will be written
45 - // with the FILE_APPEND flag
46 - if ( file_exists( $this->tmp_ticks ) ) {
47 - unlink( $this->tmp_ticks );
54 + if ( function_exists('hrtime') ) {
55 + // PHP >=7.3
56 + self::$metrics = 'hrtime';
57 + } else {
58 + self::$metrics = 'microtime';
48 59 }
49 60
50 - if ( version_compare( PHP_VERSION, '7.3', '<') ) {
51 - self::$metrics = 'microtime';
52 - } else {
53 - self::$metrics = 'hrtime';
61 + // Select theme (stylesheet::template)
62 + if (! empty( $_SERVER['HTTP_THEME'] ) ) {
63 +
64 + $theme = explode('::', $_SERVER['HTTP_THEME'] );
65 + if (! empty( $theme[1] ) ) {
66 + define('CODE_PROFILER_STYLESHEET', sanitize_file_name( $theme[0] ) );
67 + define('CODE_PROFILER_TEMPLATE', sanitize_file_name( $theme[1] ) );
68 +
69 + if ( is_file( WP_CONTENT_DIR .'/themes/'. CODE_PROFILER_STYLESHEET .'/style.css' ) ) {
70 +
71 + add_filter('pre_option_template', function () {
72 + return CODE_PROFILER_TEMPLATE;
73 + }, 1000 );
74 +
75 + add_filter('pre_option_stylesheet', function () {
76 + return CODE_PROFILER_STYLESHEET;
77 + }, 1000 );
78 +
79 + code_profiler_log_debug(
80 + sprintf(
81 + // We cannot load translation here.
82 + 'Setting theme to %s',
83 + CODE_PROFILER_STYLESHEET
84 + )
85 + );
86 + } else {
87 + code_profiler_log_error(
88 + sprintf(
89 + // We cannot load translation here.
90 + 'Unable to switch theme, %s not found',
91 + CODE_PROFILER_STYLESHEET
92 + )
93 + );
94 + }
95 + }
54 96 }
55 97
56 98 $cp_options = get_option('code-profiler');
57 99 if ( empty( $cp_options['accuracy'] ) ) {
@@ -60,11 +102,44 @@
60 102 define('CODE_PROFILER_TICKS', (int) $cp_options['accuracy'] );
61 103 }
62 104 define('CODE_PROFILER_LENGTH', 17 + strlen( (string) CODE_PROFILER_TICKS ) );
63 105
64 - register_shutdown_function( array( $this, 'code_profiler_shutdown') );
106 + if ( empty( $cp_options['buffer'] ) ||
107 + ! preg_match('/^(?:[1-9]|10)$/', $cp_options['buffer'] ) ) {
65 108
109 + $recommended = code_profiler_suggested_memory();
110 + self::$buffer = (int) $recommended * 1000000;
111 + } else {
112 + self::$buffer = $cp_options['buffer'] * 1000000;
113 + }
114 + code_profiler_log_debug(
115 + sprintf(
116 + // We cannot load translation here.
117 + 'Setting size of memory buffer to %sMB',
118 + self::$buffer / 1000000
119 + )
120 + );
121 +
122 + // File & folder exclusions
123 + if ( isset( $cp_options['exclusions'] ) ) {
124 + self::$exclusions = json_decode( $cp_options['exclusions'] );
125 + }
126 +
127 + add_filter('pre_http_request', [ $this, 'pre_http_request'], 10000, 3 );
128 + add_action('http_api_debug', [ $this, 'http_api_debug'], 10000, 5 );
129 + register_shutdown_function( [ $this, 'code_profiler_shutdown'] );
130 + code_profiler_log_debug(
131 + // We cannot load translation here.
132 + 'Starting profiler'
133 + );
66 134 require 'class-stream.php';
135 +
136 + // Clear the temporary log because the buffer will be appended to it
137 + if ( file_exists( $this->tmp_calls ) ) {
138 + unlink( $this->tmp_calls );
139 + }
140 + self::$fh = fopen( $this->tmp_calls, 'wb');
141 +
67 142 CodeProfiler_Stream::start();
68 143 register_tick_function( array( $this, 'code_profiler_tick_handler') );
69 144 }
70 145
@@ -74,10 +149,19 @@
74 149 public function code_profiler_shutdown() {
75 150
76 151 CodeProfiler_Stream::stop();
77 152
78 - $summary['memory'] = memory_get_peak_usage();
79 - $summary['queries'] = get_num_queries() - 2;
153 + fclose( self::$fh );
154 +
155 + // Summary file (metadata)
156 + $summary = [];
157 + if ( is_file( $this->tmp_rerun ) ) {
158 + $summary['rerun'] = json_decode( file_get_contents( $this->tmp_rerun ), true );
159 + unlink( $this->tmp_rerun );
160 + }
161 + $summary['memory'] = memory_get_peak_usage();
162 + $summary['queries'] = get_num_queries() - 2;
163 + $summary['precision'] = CODE_PROFILER_TICKS;
80 164 file_put_contents( $this->tmp_summary, json_encode( $summary ) );
81 165
82 166 // Catch potential error
83 167 $e = error_get_last();
@@ -97,11 +181,11 @@
97 181 if ( $res === false ) {
98 182 $msg = sprintf( $err_msg, $this->tmp_iostats );
99 183 code_profiler_log_error( $msg );
100 184 }
101 - $res = file_put_contents( $this->tmp_ticks, self::$tick_list, FILE_APPEND );
185 + $res = file_put_contents( $this->tmp_calls, self::$tick_list, FILE_APPEND );
102 186 if ( $res === false ) {
103 - $msg = sprintf( $err_msg, $this->tmp_ticks );
187 + $msg = sprintf( $err_msg, $this->tmp_calls );
104 188 code_profiler_log_error( $msg );
105 189 }
106 190 $res = file_put_contents(
107 191 $this->tmp_diskio, "read\t". CodeProfiler_Stream::$io_read ."\nwrite\t".
@@ -106,8 +190,11 @@
106 190 $res = file_put_contents(
107 191 $this->tmp_diskio, "read\t". CodeProfiler_Stream::$io_read ."\nwrite\t".
108 192 CodeProfiler_Stream::$io_write
109 193 );
194 + if (! empty( self::$connections_list ) ) {
195 + file_put_contents( $this->tmp_connections, json_encode( self::$connections_list) );
196 + }
110 197 }
111 198
112 199 /**
113 200 * Our tick handler.
@@ -136,17 +223,14 @@
136 223 self::$tick_list .= $backtrace[0]['file'];
137 224 } else {
138 225 self::$tick_list .= '-';
139 226 }
227 + $backtrace = null;
140 228
141 229 // Buffer can grow *very* big hence we flush it every 10MB by default
142 230 if ( strlen( self::$tick_list ) > self::$buffer ) {
143 231 CodeProfiler_Stream::stop();
144 - file_put_contents(
145 - $this->tmp_ticks,
146 - self::$tick_list ."\t{$start}\t". $this->time() ."\n",
147 - FILE_APPEND
148 - );
232 + fwrite( self::$fh, self::$tick_list ."\t{$start}\t". $this->time() ."\n" );
149 233 CodeProfiler_Stream::start();
150 234 self::$tick_list = '';
151 235
152 236 } else {
@@ -153,8 +237,31 @@
153 237 self::$tick_list .="\t{$start}\t". $this->time() ."\n";
154 238 }
155 239 }
156 240
241 +
242 + /**
243 + * HTTP API request.
244 + */
245 + public function pre_http_request( $preempt, $r, $url ) {
246 +
247 + if ( empty( $url ) ) {
248 + return false;
249 + }
250 + $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
251 + self::$connections_start = $this->time();
252 + self::$connections_list[ self::$connections_start ]['bt'] = $backtrace;
253 + return false;
254 + }
255 +
256 +
257 + /**
258 + * HTTP API response.
259 + */
260 + public function http_api_debug( $response, $context, $class, $parsed_args, $url ) {
261 +
262 + self::$connections_list[ self::$connections_start ]['stop'] = $this->time();
263 + }
157 264
158 265 /**
159 266 * Return time
160 267 */