diff options
Diffstat (limited to 'storage/perfschema/pfs_instr.h')
-rw-r--r-- | storage/perfschema/pfs_instr.h | 421 |
1 files changed, 371 insertions, 50 deletions
diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h index 2f6b729628e..b579c1d7902 100644 --- a/storage/perfschema/pfs_instr.h +++ b/storage/perfschema/pfs_instr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2011, 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 @@ -21,11 +21,28 @@ Performance schema instruments (declarations). */ +struct PFS_mutex_class; +struct PFS_rwlock_class; +struct PFS_cond_class; +struct PFS_file_class; +struct PFS_table_share; +struct PFS_thread_class; +struct PFS_socket_class; + +#ifdef __WIN__ +#include <winsock2.h> +#else +#include <arpa/inet.h> +#endif #include "pfs_lock.h" +#include "pfs_stat.h" #include "pfs_instr_class.h" #include "pfs_events_waits.h" +#include "pfs_events_stages.h" +#include "pfs_events_statements.h" #include "pfs_server.h" #include "lf.h" +#include "pfs_con_slice.h" /** @addtogroup Performance_schema_buffers @@ -33,13 +50,21 @@ */ struct PFS_thread; +struct PFS_host; +struct PFS_user; +struct PFS_account; +/** Base structure for wait instruments. */ struct PFS_instr { /** Internal lock. */ pfs_lock m_lock; - /** Instrument wait statistics chain. */ - PFS_single_stat_chain m_wait_stat; + /** Enabled flag. */ + bool m_enabled; + /** Timed flag. */ + bool m_timed; + /** Instrument wait statistics. */ + PFS_single_stat m_wait_stat; }; /** Instrumented mutex implementation. @see PSI_mutex. */ @@ -49,11 +74,13 @@ struct PFS_mutex : public PFS_instr const void *m_identity; /** Mutex class. */ PFS_mutex_class *m_class; + /** Instrument wait statistics. */ + PFS_single_stat m_wait_stat; /** - Mutex lock usage statistics chain. + Mutex lock usage statistics. This statistic is not exposed in user visible tables yet. */ - PFS_single_stat_chain m_lock_stat; + PFS_single_stat m_lock_stat; /** Current owner. */ PFS_thread *m_owner; /** @@ -70,16 +97,18 @@ struct PFS_rwlock : public PFS_instr const void *m_identity; /** RWLock class. */ PFS_rwlock_class *m_class; + /** Instrument wait statistics. */ + PFS_single_stat m_wait_stat; /** - RWLock read lock usage statistics chain. + RWLock read lock usage statistics. This statistic is not exposed in user visible tables yet. */ - PFS_single_stat_chain m_read_lock_stat; + PFS_single_stat m_read_lock_stat; /** - RWLock write lock usage statistics chain. + RWLock write lock usage statistics. This statistic is not exposed in user visible tables yet. */ - PFS_single_stat_chain m_write_lock_stat; + PFS_single_stat m_write_lock_stat; /** Current writer thread. */ PFS_thread *m_writer; /** Current count of readers. */ @@ -103,6 +132,8 @@ struct PFS_cond : public PFS_instr const void *m_identity; /** Condition class. */ PFS_cond_class *m_class; + /** Instrument wait statistics. */ + PFS_single_stat m_wait_stat; /** Condition instance usage statistics. */ PFS_cond_stat m_cond_stat; }; @@ -110,30 +141,173 @@ struct PFS_cond : public PFS_instr /** Instrumented File and FILE implementation. @see PSI_file. */ struct PFS_file : public PFS_instr { + uint32 get_version() + { return m_lock.get_version(); } + + /** File identity */ + const void *m_identity; /** File name. */ char m_filename[FN_REFLEN]; /** File name length in bytes. */ uint m_filename_length; /** File class. */ PFS_file_class *m_class; + /** Instrument wait statistics. */ + PFS_single_stat m_wait_stat; /** File usage statistics. */ PFS_file_stat m_file_stat; }; /** Instrumented table implementation. @see PSI_table. */ -struct PFS_table : public PFS_instr +struct PFS_table { + /** + True if table io instrumentation is enabled. + This flag is computed. + */ + bool m_io_enabled; + /** + True if table lock instrumentation is enabled. + This flag is computed. + */ + bool m_lock_enabled; + /** + True if table io instrumentation is timed. + This flag is computed. + */ + bool m_io_timed; + /** + True if table lock instrumentation is timed. + This flag is computed. + */ + bool m_lock_timed; + + /** True if table io statistics have been collected. */ + bool m_has_io_stats; + + /** True if table lock statistics have been collected. */ + bool m_has_lock_stats; + +public: + /** + Aggregate this table handle statistics to the parents. + Only use this method for handles owned by the calling code. + @sa sanitized_aggregate. + */ + void aggregate(void) + { + if (likely((m_thread_owner != NULL) && (m_has_io_stats || m_has_lock_stats))) + { + safe_aggregate(& m_table_stat, m_share, m_thread_owner); + m_has_io_stats= false; + m_has_lock_stats= false; + } + } + + /** + Aggregate this table handle statistics to the parents. + This method is safe to call on handles not owned by the calling code. + @sa aggregate + @sa sanitized_aggregate_io + @sa sanitized_aggregate_lock + */ + void sanitized_aggregate(void); + + /** + Aggregate this table handle io statistics to the parents. + This method is safe to call on handles not owned by the calling code. + */ + void sanitized_aggregate_io(void); + + /** + Aggregate this table handle lock statistics to the parents. + This method is safe to call on handles not owned by the calling code. + */ + void sanitized_aggregate_lock(void); + + /** Internal lock. */ + pfs_lock m_lock; + /** Owner. */ + PFS_thread *m_thread_owner; /** Table share. */ PFS_table_share *m_share; /** Table identity, typically a handler. */ const void *m_identity; + /** Table statistics. */ + PFS_table_stat m_table_stat; + +private: + static void safe_aggregate(PFS_table_stat *stat, + PFS_table_share *safe_share, + PFS_thread *safe_thread); + static void safe_aggregate_io(PFS_table_stat *stat, + PFS_table_share *safe_share, + PFS_thread *safe_thread); + static void safe_aggregate_lock(PFS_table_stat *stat, + PFS_table_share *safe_share, + PFS_thread *safe_thread); +}; + +/** Instrumented socket implementation. @see PSI_socket. */ +struct PFS_socket : public PFS_instr +{ + uint32 get_version() + { return m_lock.get_version(); } + + /** Socket identity, typically int */ + const void *m_identity; + /** Owning thread, if applicable */ + PFS_thread *m_thread_owner; + /** Socket file descriptor */ + uint m_fd; + /** Raw socket address */ + struct sockaddr_storage m_sock_addr; + /** Length of address */ + socklen_t m_addr_len; + /** Idle flag. */ + bool m_idle; + /** Socket class. */ + PFS_socket_class *m_class; + /** Socket usage statistics. */ + PFS_socket_stat m_socket_stat; }; /** - @def LOCKER_STACK_SIZE + @def WAIT_STACK_LOGICAL_SIZE Maximum number of nested waits. + Some waits, such as: + - "wait/io/table/sql/handler" + - "wait/lock/table/sql/handler" + are implemented by calling code in a storage engine, + that can cause nested waits (file io, mutex, ...) + Because of partitioned tables, a table io event (on the whole table) + can contain a nested table io event (on a partition). + Because of additional debug instrumentation, + waiting on what looks like a "mutex" (safe_mutex, innodb sync0sync, ...) + can cause nested waits to be recorded. + For example, a wait on innodb mutexes can lead to: + - wait/sync/mutex/innobase/some_mutex + - wait/sync/mutex/innobase/sync0sync + - wait/sync/mutex/innobase/os0sync + The max depth of the event stack must be sufficient + for these low level details to be visible. */ -#define LOCKER_STACK_SIZE 3 +#define WAIT_STACK_LOGICAL_SIZE 5 +/** + @def WAIT_STACK_BOTTOM + Maximum number dummy waits records. + One dummy record is reserved for the parent stage / statement, + at the bottom of the wait stack. +*/ +#define WAIT_STACK_BOTTOM 1 +/** + @def WAIT_STACK_SIZE + Physical size of the waits stack +*/ +#define WAIT_STACK_SIZE (WAIT_STACK_BOTTOM + WAIT_STACK_LOGICAL_SIZE) + +/** Max size of the statements stack. */ +extern uint statement_stack_max; /** @def PFS_MAX_ALLOC_RETRY @@ -142,6 +316,7 @@ struct PFS_table : public PFS_instr */ #define PFS_MAX_ALLOC_RETRY 1000 +/** The maximun number of passes in @sa PFS_scan. */ #define PFS_MAX_SCAN_PASS 2 /** @@ -155,59 +330,113 @@ struct PFS_table : public PFS_instr struct PFS_scan { public: + /** + Initialize a new scan. + @param random a random index to start from + @param max_size the max size of the interval to scan + */ void init(uint random, uint max_size); + /** + Predicate, has a next pass. + @return true if there is a next pass to perform. + */ bool has_pass() const { return (m_pass < m_pass_max); } + /** + Iterator, proceed to the next pass. + */ void next_pass() { m_pass++; } + /** First index for this pass. */ uint first() const { return m_first[m_pass]; } + /** Last index for this pass. */ uint last() const { return m_last[m_pass]; } private: + /** Current pass. */ uint m_pass; + /** Maximum number of passes. */ uint m_pass_max; + /** First element for each pass. */ uint m_first[PFS_MAX_SCAN_PASS]; + /** Last element for each pass. */ uint m_last[PFS_MAX_SCAN_PASS]; }; /** Instrumented thread implementation. @see PSI_thread. */ -struct PFS_thread +struct PFS_thread : PFS_connection_slice { + static PFS_thread* get_current_thread(void); + + /** Thread instrumentation flag. */ + bool m_enabled; + /** Current wait event in the event stack. */ + PFS_events_waits *m_events_waits_current; + /** Event ID counter */ + ulonglong m_event_id; /** Internal lock. */ pfs_lock m_lock; /** Pins for filename_hash. */ LF_PINS *m_filename_hash_pins; /** Pins for table_share_hash. */ LF_PINS *m_table_share_hash_pins; - /** Event ID counter */ - ulonglong m_event_id; - /** Thread instrumentation flag. */ - bool m_enabled; + /** Pins for setup_actor_hash. */ + LF_PINS *m_setup_actor_hash_pins; + /** Pins for setup_object_hash. */ + LF_PINS *m_setup_object_hash_pins; + /** Pins for host_hash. */ + LF_PINS *m_host_hash_pins; + /** Pins for user_hash. */ + LF_PINS *m_user_hash_pins; + /** Pins for account_hash. */ + LF_PINS *m_account_hash_pins; + /** Pins for digest_hash. */ + LF_PINS *m_digest_hash_pins; /** Internal thread identifier, unique. */ ulong m_thread_internal_id; + /** Parent internal thread identifier. */ + ulong m_parent_thread_internal_id; /** External (SHOW PROCESSLIST) thread identifier, not unique. */ ulong m_thread_id; /** Thread class. */ PFS_thread_class *m_class; - /** Size of @c m_wait_locker_stack. */ - uint m_wait_locker_count; /** - Stack of wait lockers. - This member holds the data for the table - PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT. - For most locks, only 1 wait locker is used at a given time. - For composite locks, several records are needed: - - 1 for a 'logical' wait (for example on the GLOBAL READ LOCK state) - - 1 for a 'physical' wait (for example on COND_refresh) + Stack of events waits. + This member holds the data for the table PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT. + Note that stack[0] is a dummy record that represents the parent stage/statement. + For example, assuming the following tree: + - STAGE ID 100 + - WAIT ID 101, parent STAGE 100 + - WAIT ID 102, parent wait 101 + the data in the stack will be: + stack[0].m_event_id= 100, set by the stage instrumentation + stack[0].m_event_type= STAGE, set by the stage instrumentation + stack[0].m_nesting_event_id= unused + stack[0].m_nesting_event_type= unused + stack[1].m_event_id= 101 + stack[1].m_event_type= WAIT + stack[1].m_nesting_event_id= stack[0].m_event_id= 100 + stack[1].m_nesting_event_type= stack[0].m_event_type= STAGE + stack[2].m_event_id= 102 + stack[2].m_event_type= WAIT + stack[2].m_nesting_event_id= stack[1].m_event_id= 101 + stack[2].m_nesting_event_type= stack[1].m_event_type= WAIT + + The whole point of the stack[0] record is to allow this optimization + in the code, in the instrumentation for wait events: + wait->m_nesting_event_id= (wait-1)->m_event_id; + wait->m_nesting_event_type= (wait-1)->m_event_type; + This code works for both the top level wait, and nested waits, + and works without if conditions, which helps performances. */ - PFS_wait_locker m_wait_locker_stack[LOCKER_STACK_SIZE]; + PFS_events_waits m_events_waits_stack[WAIT_STACK_SIZE]; /** True if the circular buffer @c m_waits_history is full. */ bool m_waits_history_full; /** Current index in the circular buffer @c m_waits_history. */ @@ -218,32 +447,75 @@ struct PFS_thread PERFORMANCE_SCHEMA.EVENTS_WAITS_HISTORY. */ PFS_events_waits *m_waits_history; + + /** True if the circular buffer @c m_stages_history is full. */ + bool m_stages_history_full; + /** Current index in the circular buffer @c m_stages_history. */ + uint m_stages_history_index; /** - Per thread waits aggregated statistics. + Stages history circular buffer. This member holds the data for the table - PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. + PERFORMANCE_SCHEMA.EVENTS_STAGES_HISTORY. */ - PFS_single_stat_chain *m_instr_class_wait_stats; -}; + PFS_events_stages *m_stages_history; -PFS_thread *sanitize_thread(PFS_thread *unsafe); -const char *sanitize_file_name(const char *unsafe); - -PFS_single_stat_chain* -find_per_thread_mutex_class_wait_stat(PFS_thread *thread, - PFS_mutex_class *klass); - -PFS_single_stat_chain* -find_per_thread_rwlock_class_wait_stat(PFS_thread *thread, - PFS_rwlock_class *klass); + /** True if the circular buffer @c m_statements_history is full. */ + bool m_statements_history_full; + /** Current index in the circular buffer @c m_statements_history. */ + uint m_statements_history_index; + /** + Statements history circular buffer. + This member holds the data for the table + PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_HISTORY. + */ + PFS_events_statements *m_statements_history; + + /** User name. */ + char m_username[USERNAME_LENGTH]; + /** Length of @c m_username. */ + uint m_username_length; + /** Host name. */ + char m_hostname[HOSTNAME_LENGTH]; + /** Length of @c m_hostname. */ + uint m_hostname_length; + /** Database name. */ + char m_dbname[NAME_LEN]; + /** Length of @c m_dbname. */ + uint m_dbname_length; + /** Current command. */ + int m_command; + /** Start time. */ + time_t m_start_time; + /** Processlist state. */ + const char *m_processlist_state_ptr; + /** Length of @c m_processlist_state_ptr. */ + uint m_processlist_state_length; + /** Processlist info. */ + const char *m_processlist_info_ptr; + /** Length of @c m_processlist_info_length. */ + uint m_processlist_info_length; + + PFS_events_stages m_stage_current; + + /** Size of @c m_events_statements_stack. */ + uint m_events_statements_count; + PFS_events_statements *m_statement_stack; + + PFS_host *m_host; + PFS_user *m_user; + PFS_account *m_account; +}; -PFS_single_stat_chain* -find_per_thread_cond_class_wait_stat(PFS_thread *thread, - PFS_cond_class *klass); +extern PFS_single_stat *global_instr_class_waits_array; +extern PFS_stage_stat *global_instr_class_stages_array; +extern PFS_statement_stat *global_instr_class_statements_array; -PFS_single_stat_chain* -find_per_thread_file_class_wait_stat(PFS_thread *thread, - PFS_file_class *klass); +PFS_mutex *sanitize_mutex(PFS_mutex *unsafe); +PFS_rwlock *sanitize_rwlock(PFS_rwlock *unsafe); +PFS_cond *sanitize_cond(PFS_cond *unsafe); +PFS_thread *sanitize_thread(PFS_thread *unsafe); +PFS_file *sanitize_file(PFS_file *unsafe); +PFS_socket *sanitize_socket(PFS_socket *unsafe); int init_instruments(const PFS_global_param *param); void cleanup_instruments(); @@ -266,9 +538,13 @@ PFS_file* find_or_create_file(PFS_thread *thread, PFS_file_class *klass, void release_file(PFS_file *pfs); void destroy_file(PFS_thread *thread, PFS_file *pfs); -PFS_table* create_table(PFS_table_share *share, const void *identity); +PFS_table* create_table(PFS_table_share *share, PFS_thread *opening_thread, + const void *identity); void destroy_table(PFS_table *pfs); +PFS_socket* create_socket(PFS_socket_class *socket_class, const void *identity); +void destroy_socket(PFS_socket *pfs); + /* For iterators and show status. */ extern ulong mutex_max; @@ -285,9 +561,13 @@ extern long file_handle_max; extern ulong file_handle_lost; extern ulong table_max; extern ulong table_lost; +extern ulong socket_max; +extern ulong socket_lost; extern ulong events_waits_history_per_thread; -extern ulong instr_class_per_thread; +extern ulong events_stages_history_per_thread; +extern ulong events_statements_history_per_thread; extern ulong locker_lost; +extern ulong statement_lost; /* Exposing the data directly, for iterators. */ @@ -298,10 +578,51 @@ extern PFS_thread *thread_array; extern PFS_file *file_array; extern PFS_file **file_handle_array; extern PFS_table *table_array; +extern PFS_socket *socket_array; void reset_events_waits_by_instance(); -void reset_per_thread_wait_stat(); void reset_file_instance_io(); +void reset_socket_instance_io(); + +void aggregate_all_event_names(PFS_single_stat *from_array, + PFS_single_stat *to_array); +void aggregate_all_event_names(PFS_single_stat *from_array, + PFS_single_stat *to_array_1, + PFS_single_stat *to_array_2); + +void aggregate_all_stages(PFS_stage_stat *from_array, + PFS_stage_stat *to_array); +void aggregate_all_stages(PFS_stage_stat *from_array, + PFS_stage_stat *to_array_1, + PFS_stage_stat *to_array_2); + +void aggregate_all_statements(PFS_statement_stat *from_array, + PFS_statement_stat *to_array); +void aggregate_all_statements(PFS_statement_stat *from_array, + PFS_statement_stat *to_array_1, + PFS_statement_stat *to_array_2); + +void aggregate_thread(PFS_thread *thread); +void aggregate_thread_waits(PFS_thread *thread); +void aggregate_thread_stages(PFS_thread *thread); +void aggregate_thread_statements(PFS_thread *thread); +void clear_thread_account(PFS_thread *thread); +void set_thread_account(PFS_thread *thread); + +/** Update derived flags for all mutex instances. */ +void update_mutex_derived_flags(); +/** Update derived flags for all rwlock instances. */ +void update_rwlock_derived_flags(); +/** Update derived flags for all condition instances. */ +void update_cond_derived_flags(); +/** Update derived flags for all file handles. */ +void update_file_derived_flags(); +/** Update derived flags for all table handles. */ +void update_table_derived_flags(); +/** Update derived flags for all socket instances. */ +void update_socket_derived_flags(); +/** Update derived flags for all instruments. */ +void update_instruments_derived_flags(); /** @} */ #endif |