From: Marc Alff Date: January 28 2011 1:41pm Subject: bzr commit into mysql-trunk branch (marc.alff:3567) Bug#59740 List-Archive: http://lists.mysql.com/commits/129871 X-Bug: 59740 Message-Id: <201101281342.p0SCS0hE025791@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6921652463161137799==" --===============6921652463161137799== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/malff/BZR_TREE/mysql-trunk-bug59740/ based on revid:marc.alff@stripped 3567 Marc Alff 2011-01-28 BUG#59740 Performance schema test failures on freebsd Investigation of bug 59740 shows that selects on table performance_schema.events_waits_summary_by_thread_by_event_name sometime to not return the expected rows. While the root cause of this is not identified yet, the method table_ews_by_thread_by_event_name::rnd_next() is suspected to be the origin of the failure. The code of this method can benefit from simplifications already identified with other tables, see for example table_setup_instruments::rnd_next(). This fix implements several improvements for the table scan of table performance_schema.events_waits_summary_by_thread_by_event_name. In particular: - code duplication is reduced - code complexity is reduced - the number of calls to thread_array[i].m_lock.is_populated() is reduced by a factor 200+ (the number of instruments) This is implemented by changing the iteration on threads from the innermost index (index 3) to the outermost index (index 1). While is it unclear if calling atomic operations too frequently can cause end_optimistic_lock() to fail in ::make_row(), which could be a possible root cause for the bug found, reducing the number of calls to atomic operations will make the code more robust and scalable, so implementing this cleanup is required. This fix also improves the ortho_iter test, for coverage, since it also checks table events_waits_summary_by_thread_by_event_name. modified: mysql-test/suite/perfschema/r/ortho_iter.result mysql-test/suite/perfschema/t/ortho_iter.test storage/perfschema/table_ews_by_thread_by_event_name.cc storage/perfschema/table_ews_by_thread_by_event_name.h storage/perfschema/table_ews_global_by_event_name.h === modified file 'mysql-test/suite/perfschema/r/ortho_iter.result' --- a/mysql-test/suite/perfschema/r/ortho_iter.result 2011-01-26 09:34:10 +0000 +++ b/mysql-test/suite/perfschema/r/ortho_iter.result 2011-01-28 13:40:57 +0000 @@ -154,6 +154,15 @@ status Checking table events_waits_summary_global_by_event_name ... Warnings: Warning 12000 Done +call check_instrument("wait/synch/"); +instr_name is_wait is_stage is_statement +wait/synch/ 1 0 0 +status +Checking table events_waits_summary_by_thread_by_event_name ... +status +Checking table events_waits_summary_global_by_event_name ... +Warnings: +Warning 12000 Done call check_instrument("wait/io/file/"); instr_name is_wait is_stage is_statement wait/io/file/ 1 0 0 @@ -181,6 +190,15 @@ status Checking table events_waits_summary_global_by_event_name ... Warnings: Warning 12000 Done +call check_instrument("wait/io/"); +instr_name is_wait is_stage is_statement +wait/io/ 1 0 0 +status +Checking table events_waits_summary_by_thread_by_event_name ... +status +Checking table events_waits_summary_global_by_event_name ... +Warnings: +Warning 12000 Done call check_instrument("wait/lock/table/"); instr_name is_wait is_stage is_statement wait/lock/table/ 1 0 0 @@ -190,6 +208,24 @@ status Checking table events_waits_summary_global_by_event_name ... Warnings: Warning 12000 Done +call check_instrument("wait/lock/"); +instr_name is_wait is_stage is_statement +wait/lock/ 1 0 0 +status +Checking table events_waits_summary_by_thread_by_event_name ... +status +Checking table events_waits_summary_global_by_event_name ... +Warnings: +Warning 12000 Done +call check_instrument("wait/"); +instr_name is_wait is_stage is_statement +wait/ 1 0 0 +status +Checking table events_waits_summary_by_thread_by_event_name ... +status +Checking table events_waits_summary_global_by_event_name ... +Warnings: +Warning 12000 Done call check_instrument("stage/"); instr_name is_wait is_stage is_statement stage/ 0 1 0 @@ -217,4 +253,13 @@ status Checking table events_waits_summary_global_by_event_name ... Warnings: Warning 12000 Done +call check_instrument("statement/"); +instr_name is_wait is_stage is_statement +statement/ 0 0 1 +status +Checking table events_waits_summary_by_thread_by_event_name ... +status +Checking table events_waits_summary_global_by_event_name ... +Warnings: +Warning 12000 Done drop procedure check_instrument; === modified file 'mysql-test/suite/perfschema/t/ortho_iter.test' --- a/mysql-test/suite/perfschema/t/ortho_iter.test 2011-01-26 09:34:10 +0000 +++ b/mysql-test/suite/perfschema/t/ortho_iter.test 2011-01-28 13:40:57 +0000 @@ -142,13 +142,18 @@ show status like "performance_schema%"; call check_instrument("wait/synch/mutex/"); call check_instrument("wait/synch/rwlock/"); call check_instrument("wait/synch/cond/"); +call check_instrument("wait/synch/"); call check_instrument("wait/io/file/"); call check_instrument("wait/io/net/"); call check_instrument("wait/io/table/"); +call check_instrument("wait/io/"); call check_instrument("wait/lock/table/"); +call check_instrument("wait/lock/"); +call check_instrument("wait/"); call check_instrument("stage/"); call check_instrument("statement/com/"); call check_instrument("statement/sql/"); +call check_instrument("statement/"); drop procedure check_instrument; === modified file 'storage/perfschema/table_ews_by_thread_by_event_name.cc' --- a/storage/perfschema/table_ews_by_thread_by_event_name.cc 2011-01-07 16:20:19 +0000 +++ b/storage/perfschema/table_ews_by_thread_by_event_name.cc 2011-01-28 13:40:57 +0000 @@ -115,120 +115,54 @@ void table_ews_by_thread_by_event_name:: int table_ews_by_thread_by_event_name::rnd_next(void) { PFS_thread *thread; - PFS_mutex_class *mutex_class; - PFS_rwlock_class *rwlock_class; - PFS_cond_class *cond_class; - PFS_file_class *file_class; - PFS_instr_class *table_class; + PFS_instr_class *instr_class; for (m_pos.set_at(&m_next_pos); - m_pos.has_more_view(); - m_pos.next_view()) + m_pos.has_more_thread(); + m_pos.next_thread()) { - switch (m_pos.m_index_1) - { - case pos_ews_by_thread_by_event_name::VIEW_MUTEX: - do - { - mutex_class= find_mutex_class(m_pos.m_index_2); - if (mutex_class) - { - for ( ; m_pos.has_more_thread(); m_pos.next_thread()) - { - thread= &thread_array[m_pos.m_index_3]; - if (thread->m_lock.is_populated()) - { - make_row(thread, mutex_class); - m_next_pos.set_after(&m_pos); - return 0; - } - } - m_pos.next_instrument(); - } - } while (mutex_class != NULL); - break; - case pos_ews_by_thread_by_event_name::VIEW_RWLOCK: - do - { - rwlock_class= find_rwlock_class(m_pos.m_index_2); - if (rwlock_class) - { - for ( ; m_pos.has_more_thread(); m_pos.next_thread()) - { - thread= &thread_array[m_pos.m_index_3]; - if (thread->m_lock.is_populated()) - { - make_row(thread, rwlock_class); - m_next_pos.set_after(&m_pos); - return 0; - } - } - m_pos.next_instrument(); - } - } while (rwlock_class != NULL); - break; - case pos_ews_by_thread_by_event_name::VIEW_COND: - do - { - cond_class= find_cond_class(m_pos.m_index_2); - if (cond_class) - { - for ( ; m_pos.has_more_thread(); m_pos.next_thread()) - { - thread= &thread_array[m_pos.m_index_3]; - if (thread->m_lock.is_populated()) - { - make_row(thread, cond_class); - m_next_pos.set_after(&m_pos); - return 0; - } - } - m_pos.next_instrument(); - } - } while (cond_class != NULL); - break; - case pos_ews_by_thread_by_event_name::VIEW_FILE: - do + thread= &thread_array[m_pos.m_index_1]; + + /* + Important note: the thread scan is the outer loop (index 1), + to minimize the number of calls to atomic operations. + */ + if (thread->m_lock.is_populated()) + { + for ( ; + m_pos.has_more_view(); + m_pos.next_view()) { - file_class= find_file_class(m_pos.m_index_2); - if (file_class) + switch (m_pos.m_index_2) { - for ( ; m_pos.has_more_thread(); m_pos.next_thread()) - { - thread= &thread_array[m_pos.m_index_3]; - if (thread->m_lock.is_populated()) - { - make_row(thread, file_class); - m_next_pos.set_after(&m_pos); - return 0; - } - } - m_pos.next_instrument(); + case pos_ews_by_thread_by_event_name::VIEW_MUTEX: + instr_class= find_mutex_class(m_pos.m_index_3); + break; + case pos_ews_by_thread_by_event_name::VIEW_RWLOCK: + instr_class= find_rwlock_class(m_pos.m_index_3); + break; + case pos_ews_by_thread_by_event_name::VIEW_COND: + instr_class= find_cond_class(m_pos.m_index_3); + break; + case pos_ews_by_thread_by_event_name::VIEW_FILE: + instr_class= find_file_class(m_pos.m_index_3); + break; + case pos_ews_by_thread_by_event_name::VIEW_TABLE: + instr_class= find_table_class(m_pos.m_index_3); + break; + default: + DBUG_ASSERT(false); + instr_class= NULL; + break; } - } while (file_class != NULL); - break; - case pos_ews_by_thread_by_event_name::VIEW_TABLE: - do - { - table_class= find_table_class(m_pos.m_index_2); - if (table_class) + + if (instr_class != NULL) { - for ( ; m_pos.has_more_thread(); m_pos.next_thread()) - { - thread= &thread_array[m_pos.m_index_3]; - if (thread->m_lock.is_populated()) - { - make_row(thread, table_class); - m_next_pos.set_after(&m_pos); - return 0; - } - } - m_pos.next_instrument(); + make_row(thread, instr_class); + m_next_pos.set_after(&m_pos); + return 0; } - } while (table_class != NULL); - break; - default: - break; + } } } @@ -239,63 +173,42 @@ int table_ews_by_thread_by_event_name::rnd_pos(const void *pos) { PFS_thread *thread; - PFS_mutex_class *mutex_class; - PFS_rwlock_class *rwlock_class; - PFS_cond_class *cond_class; - PFS_file_class *file_class; - PFS_instr_class *table_class; + PFS_instr_class *instr_class; set_position(pos); - DBUG_ASSERT(m_pos.m_index_3 < thread_max); + DBUG_ASSERT(m_pos.m_index_1 < thread_max); - thread= &thread_array[m_pos.m_index_3]; + thread= &thread_array[m_pos.m_index_1]; if (! thread->m_lock.is_populated()) return HA_ERR_RECORD_DELETED; - switch (m_pos.m_index_1) + switch (m_pos.m_index_2) { case pos_ews_by_thread_by_event_name::VIEW_MUTEX: - mutex_class= find_mutex_class(m_pos.m_index_2); - if (mutex_class) - { - make_row(thread, mutex_class); - return 0; - } + instr_class= find_mutex_class(m_pos.m_index_3); break; case pos_ews_by_thread_by_event_name::VIEW_RWLOCK: - rwlock_class= find_rwlock_class(m_pos.m_index_2); - if (rwlock_class) - { - make_row(thread, rwlock_class); - return 0; - } + instr_class= find_rwlock_class(m_pos.m_index_3); break; case pos_ews_by_thread_by_event_name::VIEW_COND: - cond_class= find_cond_class(m_pos.m_index_2); - if (cond_class) - { - make_row(thread, cond_class); - return 0; - } + instr_class= find_cond_class(m_pos.m_index_3); break; case pos_ews_by_thread_by_event_name::VIEW_FILE: - file_class= find_file_class(m_pos.m_index_2); - if (file_class) - { - make_row(thread, file_class); - return 0; - } + instr_class= find_file_class(m_pos.m_index_3); break; case pos_ews_by_thread_by_event_name::VIEW_TABLE: - table_class= find_table_class(m_pos.m_index_2); - if (table_class) - { - make_row(thread, table_class); - return 0; - } + instr_class= find_table_class(m_pos.m_index_3); break; + default: + DBUG_ASSERT(false); + instr_class= NULL; } + if (instr_class) + { + make_row(thread, instr_class); + return 0; + } return HA_ERR_RECORD_DELETED; } === modified file 'storage/perfschema/table_ews_by_thread_by_event_name.h' --- a/storage/perfschema/table_ews_by_thread_by_event_name.h 2011-01-07 16:20:19 +0000 +++ b/storage/perfschema/table_ews_by_thread_by_event_name.h 2011-01-28 13:40:57 +0000 @@ -49,46 +49,41 @@ struct row_ews_by_thread_by_event_name /** Position of a cursor on PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. - Index 1 on instrument view - Index 2 on instrument class (1 based) - Index 3 on thread (0 based) + Index 1 on thread (0 based) + Index 2 on instrument view + Index 3 on instrument class (1 based) */ struct pos_ews_by_thread_by_event_name : public PFS_triple_index, public PFS_instrument_view_constants { pos_ews_by_thread_by_event_name() - : PFS_triple_index(FIRST_VIEW, 1, 0) + : PFS_triple_index(0, FIRST_VIEW, 1) {} inline void reset(void) { - m_index_1= FIRST_VIEW; - m_index_2= 1; - m_index_3= 0; + m_index_1= 0; + m_index_2= FIRST_VIEW; + m_index_3= 1; } - inline bool has_more_view(void) - { return (m_index_1 <= LAST_VIEW); } - inline bool has_more_thread(void) - { return (m_index_3 < thread_max); } + { return (m_index_1 < thread_max); } - inline void next_view(void) + inline void next_thread(void) { m_index_1++; - m_index_2= 1; - m_index_3= 0; + m_index_2= FIRST_VIEW; + m_index_3= 1; } - inline void next_instrument(void) - { - m_index_2++; - m_index_3= 0; - } + inline bool has_more_view(void) + { return (m_index_2 <= LAST_VIEW); } - inline void next_thread(void) + inline void next_view(void) { - m_index_3++; + m_index_2++; + m_index_3= 1; } }; === modified file 'storage/perfschema/table_ews_global_by_event_name.h' --- a/storage/perfschema/table_ews_global_by_event_name.h 2011-01-07 16:20:19 +0000 +++ b/storage/perfschema/table_ews_global_by_event_name.h 2011-01-28 13:40:57 +0000 @@ -71,11 +71,6 @@ struct pos_ews_global_by_event_name m_index_1++; m_index_2= 1; } - - inline void next_instrument(void) - { - m_index_2++; - } }; /** Table PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME. */ --===============6921652463161137799== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-trunk-bug59740/ # testament_sha1: e4d11cc0b81bb2b70c32e7b71e0bc99b50f22cb3 # timestamp: 2011-01-28 14:41:04 +0100 # base_revision_id: marc.alff@stripped\ # 1ddvdz4m8lotyzgw # # Begin bundle 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 --===============6921652463161137799==--