maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #06804
[svoj@xxxxxxxxxxx: [Commits] Rev 4006: MDEV-5674 - Performance: my_hash_sort_bin is called too often in lp:maria/10.0]
Hi!
JFYI: we discussed this during the Barcelona meeting. I will submit table cache
part separately (not to overcomplicate this patch). Reviewers are very welcome.
Regards,
Sergey
----- Forwarded message from Sergey Vojtovich <svoj@xxxxxxxxxxx> -----
Date: Fri, 14 Feb 2014 12:25:50 +0000 (UTC)
From: Sergey Vojtovich <svoj@xxxxxxxxxxx>
To: commits@xxxxxxxxxxx
Subject: [Commits] Rev 4006: MDEV-5674 - Performance: my_hash_sort_bin is called too often in lp:maria/10.0
At lp:maria/10.0
------------------------------------------------------------
revno: 4006
revision-id: svoj@xxxxxxxxxxx-20140214122541-tenvcllk760deai8
parent: svoj@xxxxxxxxxxx-20140213071355-psk0jpsarx2u7myc
committer: Sergey Vojtovich <svoj@xxxxxxxxxxx>
branch nick: 10.0
timestamp: Fri 2014-02-14 16:25:41 +0400
message:
MDEV-5674 - Performance: my_hash_sort_bin is called too often
- reduced number of my_hash_sort_bin() calls from 4 to 2 per query.
Let MDL subsystem use pre-calculated hash value for hash
inserts and deletes.
- reduced number of memory accesses done by my_hash_sort_bin()
=== modified file 'include/hash.h'
--- a/include/hash.h 2013-09-14 01:09:36 +0000
+++ b/include/hash.h 2014-02-14 12:25:41 +0000
@@ -86,7 +86,13 @@ uchar *my_hash_first_from_hash_value(con
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);
+my_bool my_hash_insert_using_hash_value(HASH *info,
+ my_hash_value_type hash_value,
+ const uchar *record);
my_bool my_hash_delete(HASH *hash, uchar *record);
+my_bool my_hash_delete_using_hash_value(HASH *hash,
+ my_hash_value_type hash_value,
+ uchar *record);
my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key,
size_t old_key_length);
void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row);
=== modified file 'mysys/hash.c'
--- a/mysys/hash.c 2013-09-14 01:09:36 +0000
+++ b/mysys/hash.c 2014-02-14 12:25:41 +0000
@@ -380,6 +380,15 @@ static int hashcmp(const HASH *hash, HAS
my_bool my_hash_insert(HASH *info, const uchar *record)
{
+ return my_hash_insert_using_hash_value(info, rec_hashnr(info, record),
+ record);
+}
+
+
+my_bool my_hash_insert_using_hash_value(HASH *info,
+ my_hash_value_type hash_value,
+ const uchar *record)
+{
int flag;
size_t idx,halfbuff,first_index;
my_hash_value_type hash_nr;
@@ -480,7 +489,7 @@ my_bool my_hash_insert(HASH *info, const
}
/* Check if we are at the empty position */
- idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1);
+ idx= my_hash_mask(hash_value, info->blength, info->records + 1);
pos=data+idx;
if (pos == empty)
{
@@ -528,6 +537,15 @@ my_bool my_hash_insert(HASH *info, const
my_bool my_hash_delete(HASH *hash, uchar *record)
{
+ return my_hash_delete_using_hash_value(hash, rec_hashnr(hash, record),
+ record);
+}
+
+
+my_bool my_hash_delete_using_hash_value(HASH *hash,
+ my_hash_value_type hash_value,
+ uchar *record)
+{
uint pos2,idx,empty_index;
my_hash_value_type pos_hashnr, lastpos_hashnr;
size_t blength;
@@ -539,7 +557,7 @@ my_bool my_hash_delete(HASH *hash, uchar
blength=hash->blength;
data=dynamic_element(&hash->array,0,HASH_LINK*);
/* Search after record with key */
- pos= data + my_hash_mask(rec_hashnr(hash, record), blength, hash->records);
+ pos= data + my_hash_mask(hash_value, blength, hash->records);
gpos = 0;
while (pos->data != record)
=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc 2013-12-10 15:31:04 +0000
+++ b/sql/mdl.cc 2014-02-14 12:25:41 +0000
@@ -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. */
@@ -846,11 +840,10 @@ MDL_lock* MDL_map::find_or_insert(const
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 +856,14 @@ MDL_lock* MDL_map::find_or_insert(const
@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())))
{
@@ -902,7 +894,9 @@ MDL_lock* MDL_map_partition::find_or_ins
lock= MDL_lock::create(mdl_key, this);
}
- if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
+ if (!lock || my_hash_insert_using_hash_value(&m_locks,
+ mdl_key->hash_value(),
+ (uchar*) lock))
{
if (unused_lock)
{
@@ -1023,10 +1017,9 @@ MDL_map::get_lock_owner(const MDL_key *m
}
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 +1027,14 @@ MDL_map::get_lock_owner(const MDL_key *m
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)
@@ -1085,7 +1077,8 @@ void MDL_map::remove(MDL_lock *lock)
void MDL_map_partition::remove(MDL_lock *lock)
{
mysql_mutex_lock(&m_mutex);
- my_hash_delete(&m_locks, (uchar*) lock);
+ my_hash_delete_using_hash_value(&m_locks, lock->key.hash_value(),
+ (uchar*) lock);
/*
To let threads holding references to the MDL_lock object know that it was
moved to the list of unused objects or destroyed, we increment the version
=== modified file 'sql/mdl.h'
--- a/sql/mdl.h 2013-12-16 08:26:20 +0000
+++ b/sql/mdl.h 2014-02-14 12:25:41 +0000
@@ -347,12 +347,17 @@ class MDL_key
m_ptr - 1);
m_length= static_cast<uint16>(strmake(m_ptr + m_db_name_length + 2, name,
NAME_LEN) - m_ptr + 1);
+ ulong nr2= 4;
+ m_hash_value= 1;
+ my_charset_bin.coll->hash_sort(&my_charset_bin, (uchar*) m_ptr, m_length,
+ &m_hash_value, &nr2);
}
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,10 +397,15 @@ class MDL_key
{
return & m_namespace_to_wait_state_name[(int)mdl_namespace()];
}
+ ulong hash_value() const
+ {
+ return m_hash_value;
+ }
private:
uint16 m_length;
uint16 m_db_name_length;
+ ulong m_hash_value;
char m_ptr[MAX_MDLKEY_LENGTH];
static PSI_stage_info m_namespace_to_wait_state_name[NAMESPACE_END];
private:
=== modified file 'strings/ctype-bin.c'
--- a/strings/ctype-bin.c 2013-11-20 11:05:39 +0000
+++ b/strings/ctype-bin.c 2014-02-14 12:25:41 +0000
@@ -277,7 +277,9 @@ void my_hash_sort_8bit_bin(CHARSET_INFO
ulong *nr1, ulong *nr2)
{
const uchar *pos = key;
-
+ ulong tmp1= *nr1;
+ ulong tmp2= *nr2;
+
/*
Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical
@@ -286,10 +288,13 @@ void my_hash_sort_8bit_bin(CHARSET_INFO
for (; pos < (uchar*) key ; pos++)
{
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint)*pos)) + (nr1[0] << 8);
- nr2[0]+=3;
+ tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) *
+ ((uint) *pos)) + (tmp1 << 8);
+ tmp2+= 3;
}
+
+ *nr1= tmp1;
+ *nr2= tmp2;
}
@@ -297,15 +302,20 @@ void my_hash_sort_bin(CHARSET_INFO *cs _
const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{
const uchar *pos = key;
-
+ ulong tmp1= *nr1;
+ ulong tmp2= *nr2;
+
key+= len;
-
+
for (; pos < (uchar*) key ; pos++)
{
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint)*pos)) + (nr1[0] << 8);
- nr2[0]+=3;
+ tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) *
+ ((uint) *pos)) + (tmp1 << 8);
+ tmp2+= 3;
}
+
+ *nr1= tmp1;
+ *nr2= tmp2;
}
_______________________________________________
commits mailing list
commits@xxxxxxxxxxx
https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits
----- End forwarded message -----
Follow ups