PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.6.4
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.6.4
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.4, at lib/class-profiler.php

226 lines 6.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 $connections_list = [];
24 static $connections_start;
25 private $tmp_iostats;
26 private $tmp_summary;
27 private $tmp_diskio;
28 private $tmp_ticks;
29
30 /**
31 * Initialize
32 */
33 public function __construct() {
34
35 $microtime = sanitize_file_name( $_REQUEST['CODE_PROFILER_ON'] );
36
37 $this->tmp_summary = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
38 CODE_PROFILER_TMP_SUMMARY_LOG;
39 $this->tmp_iostats = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
40 CODE_PROFILER_TMP_IOSTATS_LOG;
41 $this->tmp_ticks = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
42 CODE_PROFILER_TMP_TICKS_LOG;
43 $this->tmp_diskio = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
44 CODE_PROFILER_TMP_DISKIO_LOG;
45 $this->tmp_connections = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
46 CODE_PROFILER_TMP_CONNECTIONS_LOG;
47
48 // Clear the temporary log because the buffer will be written
49 // with the FILE_APPEND flag
50 if ( file_exists( $this->tmp_ticks ) ) {
51 unlink( $this->tmp_ticks );
52 }
53
54 if ( function_exists('hrtime') ) {
55 // PHP >=7.3
56 self::$metrics = 'hrtime';
57 } else {
58 self::$metrics = 'microtime';
59 }
60
61 $cp_options = get_option('code-profiler');
62 if ( empty( $cp_options['accuracy'] ) ) {
63 define('CODE_PROFILER_TICKS', 1 );
64 } else {
65 define('CODE_PROFILER_TICKS', (int) $cp_options['accuracy'] );
66 }
67 define('CODE_PROFILER_LENGTH', 17 + strlen( (string) CODE_PROFILER_TICKS ) );
68
69 if ( empty( $cp_options['buffer'] ) ||
70 ! preg_match('/^(?:[1-9]|10)$/', $cp_options['buffer'] ) ) {
71
72 $recommended = code_profiler_suggested_memory();
73 self::$buffer = (int) $recommended * 1000000;
74 } else {
75 self::$buffer = $cp_options['buffer'] * 1000000;
76 }
77 code_profiler_log_debug(
78 sprintf(
79 esc_html__('Setting size of memory buffer to %sMB', 'code-profiler'),
80 self::$buffer / 1000000
81 )
82 );
83
84 add_filter('pre_http_request', [ $this, 'pre_http_request'], 10000, 3 );
85 add_action('http_api_debug', [ $this, 'http_api_debug'], 10000, 5 );
86 register_shutdown_function( [ $this, 'code_profiler_shutdown'] );
87 code_profiler_log_debug(
88 esc_html__('Starting profiler', 'code-profiler')
89 );
90 require 'class-stream.php';
91 CodeProfiler_Stream::start();
92 register_tick_function( array( $this, 'code_profiler_tick_handler') );
93 }
94
95 /**
96 * Save data and check for potential PHP errors.
97 */
98 public function code_profiler_shutdown() {
99
100 CodeProfiler_Stream::stop();
101
102 $summary['memory'] = memory_get_peak_usage();
103 $summary['queries'] = get_num_queries() - 2;
104 file_put_contents( $this->tmp_summary, json_encode( $summary ) );
105
106 // Catch potential error
107 $e = error_get_last();
108 if ( isset( $e['type'] ) && $e['type'] === E_ERROR ) {
109 $err = str_replace( "\n", ' - ', $e['message'] );
110 code_profiler_log_error( sprintf(
111 /* Translators: Error message, line number and script */
112 esc_html__('Error: E_ERROR (%s - line %s in %s)', 'code-profiler'),
113 esc_html( $err ),
114 (int) $e['line'],
115 esc_html( $e['file'] )
116 ));
117 }
118
119 $err_msg = esc_html__('Cannot open file for writting: %s', 'code-profiler');
120 $res = file_put_contents( $this->tmp_iostats, json_encode( CodeProfiler_Stream::$io_stats ) );
121 if ( $res === false ) {
122 $msg = sprintf( $err_msg, $this->tmp_iostats );
123 code_profiler_log_error( $msg );
124 }
125 $res = file_put_contents( $this->tmp_ticks, self::$tick_list, FILE_APPEND );
126 if ( $res === false ) {
127 $msg = sprintf( $err_msg, $this->tmp_ticks );
128 code_profiler_log_error( $msg );
129 }
130 $res = file_put_contents(
131 $this->tmp_diskio, "read\t". CodeProfiler_Stream::$io_read ."\nwrite\t".
132 CodeProfiler_Stream::$io_write
133 );
134 if (! empty( self::$connections_list ) ) {
135 file_put_contents( $this->tmp_connections, json_encode( self::$connections_list) );
136 }
137 }
138
139 /**
140 * Our tick handler.
141 */
142 public function code_profiler_tick_handler() {
143
144 $start = $this->time();
145
146 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
147 if ( isset( $backtrace[1] ) ) {
148 $el = $backtrace[1];
149 } else {
150 $el = $backtrace[0];
151 }
152
153 if ( empty( $el['file'] ) ) {
154 if ( isset( $backtrace[0]['file'] ) ) {
155 $el['file'] = $backtrace[0]['file'];
156 } else {
157 return;
158 }
159 }
160
161 self::$tick_list .= "{$el['file']}\t";
162 if ( isset( $backtrace[0]['file'][0] ) ) {
163 self::$tick_list .= $backtrace[0]['file'];
164 } else {
165 self::$tick_list .= '-';
166 }
167 $backtrace = null;
168
169 // Buffer can grow *very* big hence we flush it every 10MB by default
170 if ( strlen( self::$tick_list ) > self::$buffer ) {
171 CodeProfiler_Stream::stop();
172 file_put_contents(
173 $this->tmp_ticks,
174 self::$tick_list ."\t{$start}\t". $this->time() ."\n",
175 FILE_APPEND
176 );
177 CodeProfiler_Stream::start();
178 self::$tick_list = '';
179
180 } else {
181 self::$tick_list .="\t{$start}\t". $this->time() ."\n";
182 }
183 }
184
185
186 /**
187 * HTTP API request.
188 */
189 public function pre_http_request( $preempt, $r, $url ) {
190
191 if ( empty( $url ) ) {
192 return false;
193 }
194 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
195 self::$connections_start = $this->time();
196 self::$connections_list[ self::$connections_start ]['bt'] = $backtrace;
197 return false;
198 }
199
200
201 /**
202 * HTTP API response.
203 */
204 public function http_api_debug( $response, $context, $class, $parsed_args, $url ) {
205
206 self::$connections_list[ self::$connections_start ]['stop'] = $this->time();
207 }
208
209 /**
210 * Return time
211 */
212 private function time() {
213
214 if ( self::$metrics == 'hrtime') {
215 return hrtime( true );
216 } else {
217 return microtime( true );
218 }
219 }
220 }
221
222 new CodeProfiler_Profiler();
223
224 // =====================================================================
225 // EOF
226