Commit 95d327aa authored by Nikita Malyavin's avatar Nikita Malyavin

optimize hash api to allow "insert if not found"

parent f7b7714f
...@@ -60,20 +60,32 @@ class Open_address_hash ...@@ -60,20 +60,32 @@ class Open_address_hash
return Key_trait::get_hash_value(get_key(value)); return Key_trait::get_hash_value(get_key(value));
} }
bool insert_into_bucket(const Value &value) template <typename ElemSuitsFunc, typename GetElemFunc>
bool insert_into_bucket(const Key& key,
const ElemSuitsFunc &elem_suits,
const GetElemFunc &get_elem)
{ {
auto hash_val= to_index(hash_from_value(value)); auto hash_val= to_index(Key_trait::get_hash_value(&key));
while (!is_empty(hash_array[hash_val])) while (!is_empty(hash_array[hash_val]))
{ {
if (is_equal(hash_array[hash_val], value)) if (elem_suits(hash_array[hash_val]))
return false; return false;
hash_val= to_index(hash_val + 1); hash_val= to_index(hash_val + 1);
} }
hash_array[hash_val]= value; Value &&value= get_elem();
return true; hash_array[hash_val]= get_elem();
}; return !is_empty(value);
}
bool insert_into_bucket(const Value &value)
{
return insert_into_bucket(*get_key(value),
[&value](const Value &rhs){ return is_equal(rhs, value); },
[&value](){ return value; }
);
}
uint rehash_subsequence(uint i) uint rehash_subsequence(uint i)
{ {
...@@ -171,7 +183,7 @@ class Open_address_hash ...@@ -171,7 +183,7 @@ class Open_address_hash
public: public:
Value find(const Value &elem) const Value find(const Value &elem) const
{ {
return find(*Key_trait::get_key(elem), return find(*get_key(elem),
[&elem](const Value &rhs) { return is_equal(rhs, elem); }); [&elem](const Value &rhs) { return is_equal(rhs, elem); });
} }
...@@ -180,12 +192,9 @@ class Open_address_hash ...@@ -180,12 +192,9 @@ class Open_address_hash
{ {
if (likely(first.mark())) if (likely(first.mark()))
{ {
if (first.ptr()) if (!is_empty(first.ptr()) && elem_suits(first.ptr()))
{
if (elem_suits(first.ptr()))
return first.ptr(); return first.ptr();
} if (!is_empty(second) && elem_suits(second))
else if (!is_empty(second) && elem_suits(second))
return second; return second;
return EMPTY; return EMPTY;
...@@ -199,7 +208,7 @@ class Open_address_hash ...@@ -199,7 +208,7 @@ class Open_address_hash
} }
return EMPTY; return EMPTY;
}; }
bool erase(const Value &value) bool erase(const Value &value)
{ {
...@@ -211,7 +220,7 @@ class Open_address_hash ...@@ -211,7 +220,7 @@ class Open_address_hash
second= EMPTY; second= EMPTY;
return true; return true;
} }
else if (second && is_equal(second, value)) else if (!is_empty(second) && is_equal(second, value))
{ {
second= EMPTY; second= EMPTY;
return true; return true;
...@@ -231,30 +240,35 @@ class Open_address_hash ...@@ -231,30 +240,35 @@ class Open_address_hash
return true; return true;
} }
bool insert(const Value &value) template <typename ElemSuitsFunc, typename GetElemFunc>
bool insert(const Key &key,
const ElemSuitsFunc &elem_suits,
const GetElemFunc &get_elem)
{ {
if (first.mark()) if (first.mark())
{ {
if (is_empty(first.ptr())) if (is_empty(first.ptr()))
{ {
if (is_equal(second, value)) first.set_ptr(get_elem());
return false;
first.set_ptr(value);
return true; return true;
} }
else if (is_empty(second))
if (elem_suits(first.ptr()))
return true;
if (is_empty(second))
{ {
if (is_equal(first.ptr(), value)) second= get_elem();
return false;
second= value;
return true; return true;
} }
else
{ if (elem_suits(second))
return true;
first.set_mark(false); first.set_mark(false);
if (!init_hash_array()) if (!init_hash_array())
return false; return false;
}
} }
if (unlikely(_size == TABLE_SIZE_MAX)) if (unlikely(_size == TABLE_SIZE_MAX))
...@@ -265,12 +279,19 @@ class Open_address_hash ...@@ -265,12 +279,19 @@ class Open_address_hash
if (unlikely(((ulonglong)_size + 1) * MAX_LOAD_FACTOR > capacity)) if (unlikely(((ulonglong)_size + 1) * MAX_LOAD_FACTOR > capacity))
res= grow(capacity_power + 1); res= grow(capacity_power + 1);
res= res && insert_into_bucket(value); res= res && insert_into_bucket(key, elem_suits, get_elem);
if (res) if (res)
_size++; _size++;
return res; return res;
}; };
bool insert(const Value &value)
{
return insert(*get_key(value),
[&value](const Value &rhs){ return is_equal(rhs, value); },
[&value](){ return value; });
}
bool clear() bool clear()
{ {
if (first.mark()) if (first.mark())
......
...@@ -1964,7 +1964,7 @@ MDL_context::find_ticket(MDL_request *mdl_request, ...@@ -1964,7 +1964,7 @@ MDL_context::find_ticket(MDL_request *mdl_request,
t->m_duration == mdl_request->duration; t->m_duration == mdl_request->duration;
}; };
MDL_ticket *found_ticket= ticket_hash.find(&mdl_request->key, MDL_ticket *found_ticket= ticket_hash.find(mdl_request->key,
ticket_identical); ticket_identical);
if (!found_ticket) if (!found_ticket)
{ {
......
...@@ -5054,27 +5054,41 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx, ...@@ -5054,27 +5054,41 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx,
else else
lock_type= TL_READ; lock_type= TL_READ;
MDL_key key(MDL_key::TABLE, fk->foreign_db->str, fk->foreign_table->str); const char *db= fk->foreign_db->str;
const char *table_name= fk->foreign_table->str;
MDL_key key(MDL_key::TABLE, db, table_name);
TABLE_LIST *tl= find_fk_prelocked_table(prelocking_ctx, key, lock_type); TABLE_LIST *tl= NULL;
if (tl == NULL) bool success= prelocking_ctx->fk_table_hash.insert(key,
[db, table_name, lock_type](const TABLE_LIST *tl)
{
return tl->lock_type >= lock_type
&& strcmp(tl->table_name.str, table_name) == 0
&& strcmp(tl->db.str, db) == 0;
},
[&tl, thd]()
{ {
tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST)); tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
tl->init_one_table_for_prelocking( return tl;
fk->foreign_db, fk->foreign_table, NULL, lock_type, }
TABLE_LIST::PRELOCK_FK, table_list->belong_to_view, op, );
&prelocking_ctx->query_tables_last, &key,
table_list->for_insert_data); if (unlikely(!success))
bool success= prelocking_ctx->fk_table_hash.insert(tl);
if (!success)
{ {
my_error(ER_OUTOFMEMORY, MYF(0)); my_error(ER_OUTOFMEMORY, MYF(0));
if (arena) if (arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
}
if (tl != NULL)
{
tl->init_one_table_for_prelocking(
fk->foreign_db, fk->foreign_table, NULL, lock_type,
TABLE_LIST::PRELOCK_FK, table_list->belong_to_view, op,
&prelocking_ctx->query_tables_last, &key,
table_list->for_insert_data);
}
} }
clock_t measured_time= clock() - start; clock_t measured_time= clock() - start;
global_time_spent+= measured_time; global_time_spent+= measured_time;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment