From e5ed3fa442b0ff694c0f9b2ee58fcfcc5abd800f Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 8 Feb 2016 15:05:10 +0300 Subject: [PATCH] Bug #79455: Restore get_sched_indexer_t in 5.7 This partially reverts the fix for bug bug#20709391 "SCHED_GETCPU() IN DEFAULT GET_RND_INDEX() COULD NOT GENERATE RANDOM COUNTERS" by re-introducing get_sched_indexer_t on Linux and Windows and using it (if available) as the default indexer in ib_counter_t. It also changes InnoDB row counter updates to use the default indexer rather than override it with MySQL trx ID. In sync_array_get() use the counter_indexer_t explicitly, because other ones are not random enough per comments in the fix for bug #20709391. This in itself does not introduce any measurable performance improvements, but is rather a groundwork for further changes. --- storage/innobase/handler/ha_innodb.cc | 5 ++-- storage/innobase/include/sync0arr.ic | 2 +- storage/innobase/include/ut0counter.h | 52 ++++++++++++++++++++++++++++++++++- storage/innobase/row/row0mysql.cc | 4 +-- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7663f63..dfd11fe 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8601,8 +8601,7 @@ ha_innobase::index_read( case DB_SUCCESS: error = 0; table->status = 0; - srv_stats.n_rows_read.add( - thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1); + srv_stats.n_rows_read.inc(); break; case DB_RECORD_NOT_FOUND: @@ -8888,7 +8887,7 @@ ha_innobase::general_fetch( case DB_SUCCESS: error = 0; table->status = 0; - srv_stats.n_rows_read.add(thd_get_thread_id(trx->mysql_thd), 1); + srv_stats.n_rows_read.inc(); break; case DB_RECORD_NOT_FOUND: error = HA_ERR_END_OF_FILE; diff --git a/storage/innobase/include/sync0arr.ic b/storage/innobase/include/sync0arr.ic index a15e217..29e9d3e 100644 --- a/storage/innobase/include/sync0arr.ic +++ b/storage/innobase/include/sync0arr.ic @@ -43,7 +43,7 @@ sync_array_get() return(sync_wait_array[0]); } - return(sync_wait_array[default_indexer_t<>::get_rnd_index() + return(sync_wait_array[counter_indexer_t<>::get_rnd_index() % sync_array_size]); } diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index 6b187ec..80b4b3b 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -53,6 +53,52 @@ struct generic_indexer_t { } }; +#ifdef HAVE_SCHED_GETCPU +#include +/** Use the cpu id to index into the counter array. If it fails then +use the thread id. */ +template +struct get_sched_indexer_t : public generic_indexer_t { + /** Default constructor/destructor should be OK. */ + + enum { fast = 1 }; + + /* @return result from sched_getcpu(), the thread id if it fails. */ + static size_t get_rnd_index() UNIV_NOTHROW { + + int cpu = sched_getcpu(); + + if (cpu == -1) { + cpu = (int) os_thread_get_curr_id(); + } + + return(size_t(cpu)); + } +}; +#elif _WIN32 +template +struct get_sched_indexer_t : public generic_indexer_t { + /** Default constructor/destructor should be OK. */ + + enum { fast = 1 }; + + /* @return result from GetCurrentProcessorNumber (). */ + static size_t get_rnd_index() UNIV_NOTHROW { + + /* According to the Windows documentation, it returns the + processor number within the Processor group if the host + has more than 64 logical CPUs. We ignore that here. If the + processor number from a different group maps to the same + slot that is acceptable. We want to avoid making another + system call to determine the processor group. If this becomes + an issue, the fix is to multiply the group with the processor + number and use that, also note that the number of slots should + be increased to avoid overlap. */ + return(size_t(GetCurrentProcessorNumber())); + } +}; +#endif /* HAVE_SCHED_GETCPU */ + /** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles, to index into the counter array. See the comments for my_timer_cycles() */ template @@ -106,7 +152,11 @@ struct single_indexer_t { } }; -#define default_indexer_t counter_indexer_t +#if defined(HAVE_SCHED_GETCPU) || defined(_WIN32) +# define default_indexer_t get_sched_indexer_t +#else +# define default_indexer_t counter_indexer_t +#endif /** Class for using fuzzy counters. The counter is not protected by any mutex and the results are not guaranteed to be 100% accurate but close diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 23dea04..64424fb 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2626,9 +2626,9 @@ row_update_for_mysql_using_upd_graph( than protecting the following code with a latch. */ dict_table_n_rows_dec(node->table); - srv_stats.n_rows_deleted.add((size_t)trx->id, 1); + srv_stats.n_rows_deleted.inc(); } else { - srv_stats.n_rows_updated.add((size_t)trx->id, 1); + srv_stats.n_rows_updated.inc(); } row_update_statistics_if_needed(node->table);