diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2014-03-06 16:19:12 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2014-03-06 16:19:12 +0400 |
commit | b95c8ce530cbbd92b232324dc2c4376615bd1b5d (patch) | |
tree | 60222ef1542c97949e24dcbc4474f5484b86119b /sql | |
parent | ae87e63184a451cd0c9cf95f11f51b78bb40fbc3 (diff) | |
download | mariadb-git-b95c8ce530cbbd92b232324dc2c4376615bd1b5d.tar.gz |
MDEV-5675 - Performance: my_hash_sort_bin is called too often
Reduced number of my_hash_sort_bin() calls from 4 to 1 per query.
Reduced number of memory accesses done by my_hash_sort_bin().
Details:
- let MDL subsystem use pre-calculated hash value for hash
inserts and deletes
- let table cache use pre-calculated MDL hash value
- MDL namespace is excluded from hash value calculation, so that
hash value can be used by table cache as is
- hash value for MDL is calculated as resulting hash value + MDL
namespace
- extended hash implementation to accept user defined hash function
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mdl.cc | 42 | ||||
-rw-r--r-- | sql/mdl.h | 15 | ||||
-rw-r--r-- | sql/sql_acl.cc | 10 | ||||
-rw-r--r-- | sql/sql_base.cc | 4 | ||||
-rw-r--r-- | sql/table_cache.cc | 6 | ||||
-rw-r--r-- | sql/table_cache.h | 8 |
6 files changed, 51 insertions, 34 deletions
diff --git a/sql/mdl.cc b/sql/mdl.cc index d8aa6e1d1b4..ce2483a8d8c 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -124,15 +124,9 @@ class MDL_map_partition public: MDL_map_partition(); ~MDL_map_partition(); - inline MDL_lock *find_or_insert(const MDL_key *mdl_key, - my_hash_value_type hash_value); - unsigned long get_lock_owner(const MDL_key *key, - my_hash_value_type hash_value); + inline MDL_lock *find_or_insert(const MDL_key *mdl_key); + unsigned long get_lock_owner(const MDL_key *key); inline void remove(MDL_lock *lock); - my_hash_value_type get_key_hash(const MDL_key *mdl_key) const - { - return my_calc_hash(&m_locks, mdl_key->ptr(), mdl_key->length()); - } private: bool move_from_hash_to_lock_mutex(MDL_lock *lock); /** A partition of all acquired locks in the server. */ @@ -766,13 +760,21 @@ void MDL_map::init() } +my_hash_value_type mdl_hash_function(const CHARSET_INFO *cs, + const uchar *key, size_t length) +{ + MDL_key *mdl_key= (MDL_key*) (key - offsetof(MDL_key, m_ptr)); + return mdl_key->hash_value(); +} + + /** Initialize the partition in the container with all MDL locks. */ MDL_map_partition::MDL_map_partition() { mysql_mutex_init(key_MDL_map_mutex, &m_mutex, NULL); - my_hash_init(&m_locks, &my_charset_bin, 16 /* FIXME */, 0, 0, - mdl_locks_key, 0, 0); + my_hash_init2(&m_locks, 0, &my_charset_bin, 16 /* FIXME */, 0, 0, + mdl_locks_key, mdl_hash_function, 0, 0); }; @@ -846,11 +848,10 @@ MDL_lock* MDL_map::find_or_insert(const MDL_key *mdl_key) return lock; } - my_hash_value_type hash_value= m_partitions.at(0)->get_key_hash(mdl_key); - uint part_id= hash_value % mdl_locks_hash_partitions; + uint part_id= mdl_key->hash_value() % mdl_locks_hash_partitions; MDL_map_partition *part= m_partitions.at(part_id); - return part->find_or_insert(mdl_key, hash_value); + return part->find_or_insert(mdl_key); } @@ -863,15 +864,14 @@ MDL_lock* MDL_map::find_or_insert(const MDL_key *mdl_key) @retval NULL - Failure (OOM). */ -MDL_lock* MDL_map_partition::find_or_insert(const MDL_key *mdl_key, - my_hash_value_type hash_value) +MDL_lock* MDL_map_partition::find_or_insert(const MDL_key *mdl_key) { MDL_lock *lock; retry: mysql_mutex_lock(&m_mutex); if (!(lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks, - hash_value, + mdl_key->hash_value(), mdl_key->ptr(), mdl_key->length()))) { @@ -1023,10 +1023,9 @@ MDL_map::get_lock_owner(const MDL_key *mdl_key) } else { - my_hash_value_type hash_value= m_partitions.at(0)->get_key_hash(mdl_key); - uint part_id= hash_value % mdl_locks_hash_partitions; + uint part_id= mdl_key->hash_value() % mdl_locks_hash_partitions; MDL_map_partition *part= m_partitions.at(part_id); - res= part->get_lock_owner(mdl_key, hash_value); + res= part->get_lock_owner(mdl_key); } return res; } @@ -1034,15 +1033,14 @@ MDL_map::get_lock_owner(const MDL_key *mdl_key) unsigned long -MDL_map_partition::get_lock_owner(const MDL_key *mdl_key, - my_hash_value_type hash_value) +MDL_map_partition::get_lock_owner(const MDL_key *mdl_key) { MDL_lock *lock; unsigned long res= 0; mysql_mutex_lock(&m_mutex); lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks, - hash_value, + mdl_key->hash_value(), mdl_key->ptr(), mdl_key->length()); if (lock) diff --git a/sql/mdl.h b/sql/mdl.h index c7c445c75e1..6f31b46f17f 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -28,6 +28,7 @@ #include <my_sys.h> #include <m_string.h> #include <mysql_com.h> +#include <hash.h> #include <algorithm> @@ -347,12 +348,15 @@ public: m_ptr - 1); m_length= static_cast<uint16>(strmake(m_ptr + m_db_name_length + 2, name, NAME_LEN) - m_ptr + 1); + m_hash_value= my_hash_sort(&my_charset_bin, (uchar*) m_ptr + 1, + m_length - 1); } void mdl_key_init(const MDL_key *rhs) { memcpy(m_ptr, rhs->m_ptr, rhs->m_length); m_length= rhs->m_length; m_db_name_length= rhs->m_db_name_length; + m_hash_value= rhs->m_hash_value; } bool is_equal(const MDL_key *rhs) const { @@ -392,15 +396,26 @@ public: { return & m_namespace_to_wait_state_name[(int)mdl_namespace()]; } + my_hash_value_type hash_value() const + { + return m_hash_value + mdl_namespace(); + } + my_hash_value_type tc_hash_value() const + { + return m_hash_value; + } private: uint16 m_length; uint16 m_db_name_length; + my_hash_value_type m_hash_value; char m_ptr[MAX_MDLKEY_LENGTH]; static PSI_stage_info m_namespace_to_wait_state_name[NAMESPACE_END]; private: MDL_key(const MDL_key &); /* not implemented */ MDL_key &operator=(const MDL_key &); /* not implemented */ + friend my_hash_value_type mdl_hash_function(const CHARSET_INFO *, + const uchar *, size_t); }; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index fdb32233d92..8d9989cd748 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1085,7 +1085,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) table->use_all_columns(); (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0)); (void) my_hash_init2(&acl_roles,50, &my_charset_utf8_bin, - 0,0,0, (my_hash_get_key) acl_role_get_key, + 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0, (void (*)(void *))free_acl_role, 0); username_char_length= MY_MIN(table->field[1]->char_length(), @@ -1427,8 +1427,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) table->use_all_columns(); /* account for every role mapping */ - (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info, - 0,0,0, (my_hash_get_key) acl_role_map_get_key, 0,0); + (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0, + (my_hash_get_key) acl_role_map_get_key, 0, 0, 0); MEM_ROOT temp_root; init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); while (!(read_record_info.read_record(&read_record_info))) @@ -3734,8 +3734,8 @@ public: bool ok() { return privs != 0 || cols != 0; } void init_hash() { - my_hash_init2(&hash_columns, 4, system_charset_info, - 0, 0, 0, (my_hash_get_key) get_key_column, 0, 0); + my_hash_init2(&hash_columns, 4, system_charset_info, 0, 0, 0, + (my_hash_get_key) get_key_column, 0, 0, 0); } }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8cfb7850ae3..82f98e0604b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2296,7 +2296,9 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, retry_share: share= tdc_acquire_share(thd, table_list->db, table_list->table_name, - key, key_length, gts_flags, &table); + key, key_length, + table_list->mdl_request.key.tc_hash_value(), + gts_flags, &table); if (!share) { diff --git a/sql/table_cache.cc b/sql/table_cache.cc index ac6621226ef..fbafd8e0c9f 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -664,16 +664,14 @@ void tdc_unlock_share(TABLE_SHARE *share) */ TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, const char *table_name, - const char *key, uint key_length, uint flags, + const char *key, uint key_length, + my_hash_value_type hash_value, uint flags, TABLE **out_table) { TABLE_SHARE *share; bool was_unused; - my_hash_value_type hash_value; DBUG_ENTER("tdc_acquire_share"); - hash_value= my_calc_hash(&tdc_hash, (uchar*) key, key_length); - mysql_rwlock_rdlock(&LOCK_tdc); share= (TABLE_SHARE*) my_hash_search_using_hash_value(&tdc_hash, hash_value, (uchar*) key, diff --git a/sql/table_cache.h b/sql/table_cache.h index a30a07b8357..6da6a667792 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -40,6 +40,7 @@ extern void tdc_unlock_share(TABLE_SHARE *share); extern TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, const char *table_name, const char *key, uint key_length, + my_hash_value_type hash_value, uint flags, TABLE **out_table); extern void tdc_release_share(TABLE_SHARE *share); extern bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, @@ -88,7 +89,9 @@ static inline TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, const char *key, uint key_length, uint flags) { - return tdc_acquire_share(thd, db, table_name, key, key_length, flags, 0); + return tdc_acquire_share(thd, db, table_name, key, key_length, + my_hash_sort(&my_charset_bin, (uchar*) key, + key_length), flags, 0); } @@ -120,7 +123,8 @@ static inline TABLE_SHARE *tdc_acquire_share_shortlived(THD *thd, TABLE_LIST *tl { const char *key; uint key_length= get_table_def_key(tl, &key); - return tdc_acquire_share(thd, tl->db, tl->table_name, key, key_length, flags); + return tdc_acquire_share(thd, tl->db, tl->table_name, key, key_length, + tl->mdl_request.key.tc_hash_value(), flags, 0); } |