From a175314c3e5827eb193872241446f2f8f5c9d33c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 20:07:14 +0200 Subject: Adding upstream version 1:10.5.12. Signed-off-by: Daniel Baumann --- sql/sql_profile.h | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 sql/sql_profile.h (limited to 'sql/sql_profile.h') diff --git a/sql/sql_profile.h b/sql/sql_profile.h new file mode 100644 index 00000000..85018a25 --- /dev/null +++ b/sql/sql_profile.h @@ -0,0 +1,336 @@ +/* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _SQL_PROFILE_H +#define _SQL_PROFILE_H + +class Item; +struct TABLE_LIST; +class THD; +class ST_FIELD_INFO; +typedef struct st_schema_table ST_SCHEMA_TABLE; + +namespace Show { +extern ST_FIELD_INFO query_profile_statistics_info[]; +} // namespace Show + +int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); +int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); + + +#define PROFILE_NONE (uint)0 +#define PROFILE_CPU (uint)(1<<0) +#define PROFILE_MEMORY (uint)(1<<1) +#define PROFILE_BLOCK_IO (uint)(1<<2) +#define PROFILE_CONTEXT (uint)(1<<3) +#define PROFILE_PAGE_FAULTS (uint)(1<<4) +#define PROFILE_IPC (uint)(1<<5) +#define PROFILE_SWAPS (uint)(1<<6) +#define PROFILE_SOURCE (uint)(1<<16) +#define PROFILE_ALL (uint)(~0) + + +#if defined(ENABLED_PROFILING) +#include "sql_priv.h" +#include "unireg.h" + +#ifdef __WIN__ +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +extern PSI_memory_key key_memory_queue_item; + +class PROF_MEASUREMENT; +class QUERY_PROFILE; +class PROFILING; + + +/** + Implements a persistent FIFO using server List method names. Not + thread-safe. Intended to be used on thread-local data only. +*/ +template class Queue +{ +private: + + struct queue_item + { + T *payload; + struct queue_item *next, *previous; + }; + + struct queue_item *first, *last; + +public: + Queue() + { + elements= 0; + first= last= NULL; + } + + void empty() + { + struct queue_item *i, *after_i; + for (i= first; i != NULL; i= after_i) + { + after_i= i->next; + my_free(i); + } + elements= 0; + } + + ulong elements; /* The count of items in the Queue */ + + void push_back(T *payload) + { + struct queue_item *new_item; + + new_item= (struct queue_item *) my_malloc(key_memory_queue_item, + sizeof(struct queue_item), MYF(0)); + + new_item->payload= payload; + + if (first == NULL) + first= new_item; + if (last != NULL) + { + DBUG_ASSERT(last->next == NULL); + last->next= new_item; + } + new_item->previous= last; + new_item->next= NULL; + last= new_item; + + elements++; + } + + T *pop() + { + struct queue_item *old_item= first; + T *ret= NULL; + + if (first == NULL) + { + DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue")); + return NULL; + } + + ret= old_item->payload; + if (first->next != NULL) + first->next->previous= NULL; + else + last= NULL; + first= first->next; + + my_free(old_item); + elements--; + + return ret; + } + + bool is_empty() + { + DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL))); + return (elements == 0); + } + + void *new_iterator() + { + return first; + } + + void *iterator_next(void *current) + { + return ((struct queue_item *) current)->next; + } + + T *iterator_value(void *current) + { + return ((struct queue_item *) current)->payload; + } + +}; + + +/** + A single entry in a single profile. +*/ +class PROF_MEASUREMENT +{ +private: + friend class QUERY_PROFILE; + friend class PROFILING; + + QUERY_PROFILE *profile; + char *status; +#ifdef HAVE_GETRUSAGE + struct rusage rusage; +#elif defined(_WIN32) + FILETIME ftKernel, ftUser; + IO_COUNTERS io_count; + PROCESS_MEMORY_COUNTERS mem_count; +#endif + + char *function; + char *file; + unsigned int line; + + ulong m_seq; + double time_usecs; + char *allocated_status_memory; + + void set_label(const char *status_arg, const char *function_arg, + const char *file_arg, unsigned int line_arg); + void clean_up(); + + PROF_MEASUREMENT(); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg); + ~PROF_MEASUREMENT(); + void collect(); +}; + + +/** + The full profile for a single query, and includes multiple PROF_MEASUREMENT + objects. +*/ +class QUERY_PROFILE +{ +private: + friend class PROFILING; + + PROFILING *profiling; + + query_id_t profiling_query_id; /* Session-specific id. */ + char *query_source; + + double m_start_time_usecs; + double m_end_time_usecs; + ulong m_seq_counter; + Queue entries; + + + QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg); + ~QUERY_PROFILE(); + + void set_query_source(char *query_source_arg, size_t query_length_arg); + + /* Add a profile status change to the current profile. */ + void new_status(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg); + + /* Reset the contents of this profile entry. */ + void reset(); + + /* Show this profile. This is called by PROFILING. */ + bool show(uint options); +}; + + +/** + Profiling state for a single THD; contains multiple QUERY_PROFILE objects. +*/ +class PROFILING +{ +private: + friend class PROF_MEASUREMENT; + friend class QUERY_PROFILE; + + /* + Not the system query_id, but a counter unique to profiling. + */ + query_id_t profile_id_counter; + THD *thd; + bool keeping; + bool enabled; + + QUERY_PROFILE *current; + QUERY_PROFILE *last; + Queue history; + + query_id_t next_profile_id() { return(profile_id_counter++); } + +public: + PROFILING(); + ~PROFILING(); + + /** + At a point in execution where we know the query source, save the text + of it in the query profile. + + This must be called exactly once per descrete statement. + */ + void set_query_source(char *query_source_arg, size_t query_length_arg) + { + if (unlikely(current)) + current->set_query_source(query_source_arg, query_length_arg); + } + + /** + Prepare to start processing a new query. It is an error to do this + if there's a query already in process; nesting is not supported. + + @param initial_state (optional) name of period before first state change + */ + void start_new_query(const char *initial_state= "Starting") + { + DBUG_ASSERT(!current); + if (unlikely(enabled)) + current= new QUERY_PROFILE(this, initial_state); + } + + void discard_current_query(); + + void finish_current_query() + { + if (unlikely(current)) + finish_current_query_impl(); + } + + void finish_current_query_impl(); + + void status_change(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg) + { + if (unlikely(current)) + current->new_status(status_arg, function_arg, file_arg, line_arg); + } + + inline void set_thd(THD *thd_arg) + { + thd= thd_arg; + reset(); + } + + /* SHOW PROFILES */ + bool show_profiles(); + + /* ... from INFORMATION_SCHEMA.PROFILING ... */ + int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); + void reset(); + void restart(); +}; + +# endif /* ENABLED_PROFILING */ +#endif /* _SQL_PROFILE_H */ -- cgit v1.2.3