1 # name : profiling_slow.patch
2 # introduced : 11 or before
3 # maintainer : Yasufumi
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
9 +++ b/mysql-test/r/percona_bug643149.result
11 +SET @old_slow_query_log_file=@@global.slow_query_log_file;
12 +SET GLOBAL slow_query_log=on;
13 +SET LOCAL profiling_server=on;
14 +SET LOCAL long_query_time=0;
15 +SET GLOBAL slow_query_log_file='MYSQLTEST_VARDIR/percona_bug643149_slow.log';;
19 +# User@Host: root[root] @ localhost []
20 +# Thread_id: X Schema: test Last_errno: X Killed: X
21 +# Query_time: X.X Lock_time: X.X Rows_sent: X Rows_examined: X Rows_affected: X Rows_read: X
22 +# Bytes_sent: X Tmp_tables: X Tmp_disk_tables: X Tmp_table_sizes: X
23 +# Profile_starting: X.X Profile_starting_cpu: X.X Profile_Opening_tables: X.X Profile_Opening_tables_cpu: X.X Profile_query_end: X.X Profile_query_end_cpu: X.X Profile_freeing_items: X.X Profile_freeing_items_cpu: X.X Profile_logging_slow_query: X.X Profile_logging_slow_query_cpu: X.X
24 +# Profile_total: X.X Profile_total_cpu: X.X
25 +# User@Host: root[root] @ localhost []
26 +# Thread_id: X Schema: test Last_errno: X Killed: X
27 +# Query_time: X.X Lock_time: X.X Rows_sent: X Rows_examined: X Rows_affected: X Rows_read: X
28 +# Bytes_sent: X Tmp_tables: X Tmp_disk_tables: X Tmp_table_sizes: X
29 +# Profile_starting: X.X Profile_starting_cpu: X.X Profile_checking_permissions: X.X Profile_checking_permissions_cpu: X.X Profile_Opening_tables: X.X Profile_Opening_tables_cpu: X.X Profile_init: X.X Profile_init_cpu: X.X Profile_optimizing: X.X Profile_optimizing_cpu: X.X Profile_executing: X.X Profile_executing_cpu: X.X Profile_end: X.X Profile_end_cpu: X.X Profile_query_end: X.X Profile_query_end_cpu: X.X Profile_freeing_items: X.X Profile_freeing_items_cpu: X.X Profile_logging_slow_query: X.X Profile_logging_slow_query_cpu: X.X
30 +# Profile_total: X.X Profile_total_cpu: X.X
31 +SET GLOBAL slow_query_log_file=@old_slow_query_log_file;
33 +++ b/mysql-test/t/percona_bug643149.test
36 +# This test suffers from server
37 +# Bug#38124 "general_log_file" variable silently unset when using expression
39 +# SET GLOBAL general_log_file = @<whatever>
40 +# SET GLOBAL slow_query_log = @<whatever>
41 +# cause that the value of these server system variables is set to default
42 +# instead of the assigned values. There comes no error message or warning.
43 +# If this bug is fixed please
44 +# 1. try this test with "let $fixed_bug38124 = 0;"
45 +# 2. remove all workarounds if 1. was successful.
46 +let $fixed_bug38124 = 0;
48 +SET @old_slow_query_log_file=@@global.slow_query_log_file;
49 +SET GLOBAL slow_query_log=on;
50 +SET LOCAL profiling_server=on;
51 +SET LOCAL long_query_time=0;
53 +let slogfile=$MYSQLTEST_VARDIR/percona_bug643149_slow.log;
54 +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
55 +--eval SET GLOBAL slow_query_log_file='$slogfile';
57 +--disable_ps_protocol
62 + $slogfile= $ENV{'slogfile'};
64 + open(FILE, "$slogfile") or
65 + die("Unable to read slow query log file $slogfile: $!\n");
68 + next if (/^# Time:/);
74 + open(FILE, '>', "$slogfile");
78 +SET GLOBAL slow_query_log_file=@old_slow_query_log_file;
83 + let $my_var = `SELECT @old_slow_query_log_file`;
84 + eval SET @@global.slow_query_log_file = '$my_var';
88 +++ b/patch_info/profiling_slow.info
90 +File=profiling_slow.info
91 +Name=profiling from SHOW PROFILE to slow.log
93 +Author=Percona <info@percona.com>
98 +Initial implementation
101 @@ -2436,6 +2436,11 @@
102 my_b_printf(&log_file,"# No InnoDB statistics available for this query\n") == (uint) -1)
106 +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
107 + thd->profiling.print_current(&log_file);
110 if (thd->db && strcmp(thd->db, db))
111 { // Database changed
112 if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
115 @@ -5809,6 +5809,8 @@
117 OPT_PORT_OPEN_TIMEOUT,
119 + OPT_PROFILING_SERVER,
120 + OPT_PROFILING_USE_GETRUSAGE,
121 OPT_KEEP_FILES_ON_CREATE,
124 @@ -6424,6 +6426,16 @@
125 &global_system_variables.profiling_history_size,
126 &max_system_variables.profiling_history_size,
127 0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
128 + {"profiling_server", OPT_PROFILING_SERVER,
129 + "Enable profiling of all threads",
130 + (uchar**) &global_system_variables.profiling_server,
131 + (uchar**) &max_system_variables.profiling_server, 0, GET_BOOL,
132 + OPT_ARG, 0, 0, 0, 0, 0, 0 },
133 + {"profiling_use_getrusage", OPT_PROFILING_USE_GETRUSAGE,
134 + "Enable getrusage function call for profiling",
135 + (uchar**) &global_system_variables.profiling_use_getrusage,
136 + (uchar**) &max_system_variables.profiling_use_getrusage, 0, GET_BOOL,
137 + OPT_ARG, 0, 0, 0, 0, 0, 0 },
139 {"relay-log", OPT_RELAY_LOG,
140 "The location and name to use for relay logs.",
144 ulonglong(OPTION_PROFILING));
145 static sys_var_thd_ulong sys_profiling_history_size(&vars, "profiling_history_size",
146 &SV::profiling_history_size);
147 +static sys_var_thd_bool sys_profiling_server(&vars, "profiling_server",
148 + &SV::profiling_server);
149 +static sys_var_thd_bool sys_profiling_use_getrusage(&vars, "profiling_use_getrusage",
150 + &SV::profiling_use_getrusage);
153 /* Local state variables */
154 --- a/sql/sql_class.h
155 +++ b/sql/sql_class.h
157 ulong optimizer_switch;
158 ulong preload_buff_size;
159 ulong profiling_history_size;
160 + my_bool profiling_server;
161 + my_bool profiling_use_getrusage;
162 ulong query_cache_type;
163 ulong read_buff_size;
164 ulong read_rnd_buff_size;
165 --- a/sql/sql_profile.cc
166 +++ b/sql/sql_profile.cc
169 time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */
170 #ifdef HAVE_GETRUSAGE
171 - getrusage(RUSAGE_SELF, &rusage);
172 + if ((profile->get_profiling())->enabled_getrusage())
173 + getrusage(RUSAGE_SELF, &rusage);
176 +#ifdef HAVE_CLOCK_GETTIME
177 + struct timespec tp;
179 + if (!(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
181 + cpu_time_usecs= tp.tv_sec*1000000000.0 + tp.tv_nsec;
192 finish_current_query();
195 - enabled= (((thd)->options & OPTION_PROFILING) != 0);
196 + enabled= (((thd)->options & OPTION_PROFILING) != 0) || ( thd->variables.profiling_server );
198 if (! enabled) DBUG_VOID_RETURN;
201 status_change("ending", NULL, NULL, 0);
203 if ((enabled) && /* ON at start? */
204 - ((thd->options & OPTION_PROFILING) != 0) && /* and ON at end? */
205 + (((thd->options & OPTION_PROFILING) != 0) ||
206 + (thd->variables.profiling_server)) && /* and ON at end? */
207 (current->query_source != NULL) &&
208 (! current->entries.is_empty()))
210 @@ -482,6 +497,118 @@
214 +bool PROFILING::enabled_getrusage()
216 + return thd->variables.profiling_use_getrusage;
220 + For a given profile entry specified by a name and 2 time measurements,
221 + print its normalized name (i.e. with all spaces replaced with underscores)
222 + along with its wall clock and CPU time.
225 +static void my_b_print_status(IO_CACHE *log_file, const char *status,
226 + PROF_MEASUREMENT *start, PROF_MEASUREMENT *stop)
228 + DBUG_ENTER("my_b_print_status");
229 + DBUG_ASSERT(log_file != NULL && status != NULL);
230 + char query_time_buff[22+7];
233 + my_b_printf(log_file, "Profile_");
234 + for (tmp= status; *tmp; tmp++)
235 + my_b_write_byte(log_file, *tmp == ' ' ? '_' : *tmp);
237 + snprintf(query_time_buff, sizeof(query_time_buff), "%.6f",
238 + (stop->time_usecs - start->time_usecs) / (1000.0 * 1000));
239 + my_b_printf(log_file, ": %s ", query_time_buff);
241 + my_b_printf(log_file, "Profile_");
242 + for (tmp= status; *tmp; tmp++)
243 + my_b_write_byte(log_file, *tmp == ' ' ? '_' : *tmp);
244 + my_b_printf(log_file, "_cpu: ");
246 + snprintf(query_time_buff, sizeof(query_time_buff), "%.6f",
247 + (stop->cpu_time_usecs - start->cpu_time_usecs) /
248 + (1000.0 * 1000 * 1000));
249 + my_b_printf(log_file, "%s ", query_time_buff);
255 + Print output for current query to file
258 +int PROFILING::print_current(IO_CACHE *log_file)
260 + DBUG_ENTER("PROFILING::print_current");
261 + ulonglong row_number= 0;
263 + QUERY_PROFILE *query;
264 + /* Get current query */
265 + if (current == NULL)
272 + my_b_printf(log_file, "# ");
274 + void *entry_iterator;
275 + PROF_MEASUREMENT *entry= NULL, *previous= NULL, *first= NULL;
276 + /* ...and for each query, go through all its state-change steps. */
277 + for (entry_iterator= query->entries.new_iterator();
278 + entry_iterator != NULL;
279 + entry_iterator= query->entries.iterator_next(entry_iterator),
280 + previous=entry, row_number++)
282 + entry= query->entries.iterator_value(entry_iterator);
284 + /* Skip the first. We count spans of fence, not fence-posts. */
285 + if (previous == NULL) {first= entry; continue;}
287 + if (thd->lex->sql_command == SQLCOM_SHOW_PROFILE)
290 + We got here via a SHOW command. That means that we stored
291 + information about the query we wish to show and that isn't
292 + in a WHERE clause at a higher level to filter out rows we
295 + Because that functionality isn't available in the server yet,
296 + we must filter here, at the wrong level. Once one can con-
297 + struct where and having conditions at the SQL layer, then this
298 + condition should be ripped out.
300 + if (thd->lex->profile_query_id == 0) /* 0 == show final query */
307 + if (thd->lex->profile_query_id != query->profiling_query_id)
312 + my_b_print_status(log_file, previous->status, previous, entry);
315 + my_b_write_byte(log_file, '\n');
316 + if ((entry != NULL) && (first != NULL))
318 + my_b_printf(log_file, "# ");
319 + my_b_print_status(log_file, "total", first, entry);
320 + my_b_write_byte(log_file, '\n');
327 Fill the information schema table, "query_profile", as defined in show.cc .
328 There are two ways to get to this function: Selecting from the information
331 #ifdef HAVE_GETRUSAGE
333 + if (enabled_getrusage())
335 my_decimal cpu_utime_decimal, cpu_stime_decimal;
337 double2my_decimal(E_DEC_FATAL_ERROR,
339 table->field[14]->store((uint32)(entry->rusage.ru_nswap -
340 previous->rusage.ru_nswap), true);
341 table->field[14]->set_notnull();
344 /* TODO: Add swap info for non-BSD systems */
346 --- a/sql/sql_profile.h
347 +++ b/sql/sql_profile.h
348 @@ -168,11 +168,15 @@
350 class PROF_MEASUREMENT
353 - friend class QUERY_PROFILE;
354 - friend class PROFILING;
356 QUERY_PROFILE *profile;
358 + char *allocated_status_memory;
360 + void set_label(const char *status_arg, const char *function_arg,
361 + const char *file_arg, unsigned int line_arg);
366 #ifdef HAVE_GETRUSAGE
367 struct rusage rusage;
372 - char *allocated_status_memory;
374 - void set_label(const char *status_arg, const char *function_arg,
375 - const char *file_arg, unsigned int line_arg);
378 + double cpu_time_usecs;
380 PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg);
381 PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg,
384 /* Show this profile. This is called by PROFILING. */
385 bool show(uint options);
389 + inline PROFILING * get_profiling() { return profiling; };
397 bool show_profiles();
398 + bool enabled_getrusage();
400 /* ... from INFORMATION_SCHEMA.PROFILING ... */
401 int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond);
402 + int print_current(IO_CACHE *log_file);
405 # endif /* HAVE_PROFILING */