From d3540b216f2d39126d77985db3f7639eb45bf967 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 9 Oct 2009 14:22:22 +0200 Subject: [PATCH] A minor change to MySQL's hash where calculation of hash can be done separately to avoid doing it under contended mutex locks --- include/hash.h | 9 +++++++++ mysys/hash.c | 29 +++++++++++++++++++++++++++-- sql/sql_base.cc | 9 +++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/hash.h b/include/hash.h index 629b404e8a7..b6fc365ab76 100644 --- a/include/hash.h +++ b/include/hash.h @@ -45,6 +45,7 @@ extern "C" { #define hash_element my_hash_element #define hash_search my_hash_search #define hash_first my_hash_first +#define hash_first_from_hash_value my_hash_first_from_hash_value #define hash_next my_hash_next #define hash_insert my_hash_insert #define hash_delete my_hash_delete @@ -94,8 +95,16 @@ void my_hash_free(HASH *tree); void my_hash_reset(HASH *hash); uchar *my_hash_element(HASH *hash, ulong idx); uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); +uchar *my_hash_search_using_hash_value(const HASH *info, uint hash_value, + const uchar *key, size_t length); +uint my_calc_hash(const HASH *info, const uchar *key, size_t length); uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); +uchar *my_hash_first_from_hash_value(const HASH *info, + uint hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *state); uchar *my_hash_next(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info, const uchar *data); diff --git a/mysys/hash.c b/mysys/hash.c index 63933abb085..367ac8713dd 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -214,6 +214,20 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) return my_hash_first(hash, key, length, &state); } +uchar* my_hash_search_using_hash_value(const HASH *hash, + uint hash_value, + const uchar *key, + size_t length) +{ + HASH_SEARCH_STATE state; + return my_hash_first_from_hash_value(hash, hash_value, + key, length, &state); +} + +uint my_calc_hash(const HASH *hash, const uchar *key, size_t length) +{ + return calc_hash(hash, key, length ? length : hash->key_length); +} /* Search after a record based on a key @@ -223,15 +237,26 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) +{ + return my_hash_first_from_hash_value(hash, + calc_hash(hash, key, length ? length : hash->key_length), + key, length, current_record); +} + +uchar* my_hash_first_from_hash_value(const HASH *hash, + uint hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("my_hash_first"); + DBUG_ENTER("my_hash_first_from_hash_value"); flag=1; if (hash->records) { - idx= my_hash_mask(calc_hash(hash, key, length ? length : hash->key_length), + idx= my_hash_mask(hash_value, hash->blength, hash->records); do { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b81070000b3..064d277e0b4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2513,6 +2513,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; + uint hash_value; HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); @@ -2702,6 +2703,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, on disk. */ + hash_value= my_calc_hash(&open_cache, (uchar*) key, key_length); VOID(pthread_mutex_lock(&LOCK_open)); /* @@ -2744,8 +2746,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, an implicit "pending locks queue" - see wait_for_locked_table_names for details. */ - for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, - &state); + for (table= (TABLE*) hash_first_from_hash_value(&open_cache, + hash_value, + (uchar*) key, + key_length, + &state); table && table->in_use ; table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state))