mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-22930 Unnecessary contention on rw_lock_list_mutex in ibuf_dummy_index_create()
1. Do not initialize dict_table_t::stats_latch in ibuf 2. Remove overengineering in GenericPolicy to speed up things dict_mem_table_create(): add new argument init_stats_latch ibuf_dummy_index_create(): do not initialize dict_table_t::stats_latch GenericPolicy: add new members m_filename and m_line sync_file_create_register() sync_file_created_deregister() sync_file_created_get() CreateTracker: remove rw_lock_t::created: a new debug member
This commit is contained in:
parent
1ae008d272
commit
0e86254b05
8 changed files with 61 additions and 222 deletions
|
@ -124,19 +124,25 @@ bool dict_col_t::same_encoding(uint16_t a, uint16_t b)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
/** Creates a table memory object.
|
||||
@param[in] name table name
|
||||
@param[in] space tablespace
|
||||
@param[in] n_cols total number of columns including virtual and
|
||||
non-virtual columns
|
||||
@param[in] n_v_cols number of virtual columns
|
||||
@param[in] flags table flags
|
||||
@param[in] flags2 table flags2
|
||||
@param[in] init_stats_latch whether to init the stats latch
|
||||
@return own: table object */
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
const char* name, /*!< in: table name */
|
||||
fil_space_t* space, /*!< in: tablespace */
|
||||
ulint n_cols, /*!< in: total number of columns including
|
||||
virtual and non-virtual columns */
|
||||
ulint n_v_cols,/*!< in: number of virtual columns */
|
||||
ulint flags, /*!< in: table flags */
|
||||
ulint flags2) /*!< in: table flags2 */
|
||||
const char* name,
|
||||
fil_space_t* space,
|
||||
ulint n_cols,
|
||||
ulint n_v_cols,
|
||||
ulint flags,
|
||||
ulint flags2,
|
||||
bool init_stats_latch)
|
||||
{
|
||||
dict_table_t* table;
|
||||
mem_heap_t* heap;
|
||||
|
@ -204,8 +210,11 @@ dict_mem_table_create(
|
|||
new(&table->foreign_set) dict_foreign_set();
|
||||
new(&table->referenced_set) dict_foreign_set();
|
||||
|
||||
rw_lock_create(dict_table_stats_key, &table->stats_latch,
|
||||
SYNC_INDEX_TREE);
|
||||
if (init_stats_latch) {
|
||||
rw_lock_create(dict_table_stats_key, &table->stats_latch,
|
||||
SYNC_INDEX_TREE);
|
||||
table->stats_latch_inited = true;
|
||||
}
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
@ -249,7 +258,9 @@ dict_mem_table_free(
|
|||
|
||||
UT_DELETE(table->s_cols);
|
||||
|
||||
rw_lock_free(&table->stats_latch);
|
||||
if (table->stats_latch_inited) {
|
||||
rw_lock_free(&table->stats_latch);
|
||||
}
|
||||
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
|
|
@ -1309,7 +1309,7 @@ ibuf_dummy_index_create(
|
|||
dict_index_t* index;
|
||||
|
||||
table = dict_mem_table_create("IBUF_DUMMY", NULL, n, 0,
|
||||
comp ? DICT_TF_COMPACT : 0, 0);
|
||||
comp ? DICT_TF_COMPACT : 0, 0, false);
|
||||
|
||||
index = dict_mem_index_create(table, "IBUF_DUMMY", 0, n);
|
||||
|
||||
|
|
|
@ -297,22 +297,21 @@ parent table will fail, and user has to drop excessive foreign constraint
|
|||
before proceeds. */
|
||||
#define FK_MAX_CASCADE_DEL 15
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
/** Creates a table memory object.
|
||||
@param[in] name table name
|
||||
@param[in] space tablespace
|
||||
@param[in] n_cols total number of columns including virtual and
|
||||
non-virtual columns
|
||||
@param[in] n_v_cols number of virtual columns
|
||||
@param[in] flags table flags
|
||||
@param[in] flags2 table flags2
|
||||
@param[in] init_stats_latch whether to init the stats latch
|
||||
@return own: table object */
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
const char* name, /*!< in: table name */
|
||||
fil_space_t* space, /*!< in: tablespace */
|
||||
ulint n_cols, /*!< in: total number of columns
|
||||
including virtual and non-virtual
|
||||
columns */
|
||||
ulint n_v_cols, /*!< in: number of virtual columns */
|
||||
ulint flags, /*!< in: table flags */
|
||||
ulint flags2); /*!< in: table flags2 */
|
||||
/****************************************************************//**
|
||||
Free a table memory object. */
|
||||
dict_table_t *dict_mem_table_create(const char *name, fil_space_t *space,
|
||||
ulint n_cols, ulint n_v_cols, ulint flags,
|
||||
ulint flags2, bool init_stats_latch= true);
|
||||
/****************************************************************/ /**
|
||||
Free a table memory object. */
|
||||
void
|
||||
dict_mem_table_free(
|
||||
/*================*/
|
||||
|
@ -2146,6 +2145,8 @@ public:
|
|||
performance reasons. */
|
||||
rw_lock_t stats_latch;
|
||||
|
||||
bool stats_latch_inited= false;
|
||||
|
||||
/** TRUE if statistics have been calculated the first time after
|
||||
database startup or table creation. */
|
||||
unsigned stat_initialized:1;
|
||||
|
|
|
@ -220,7 +220,8 @@ public:
|
|||
|
||||
meta.get_counter()->single_register(&m_count);
|
||||
|
||||
sync_file_created_register(this, filename, uint16_t(line));
|
||||
m_filename = filename;
|
||||
m_line = line;
|
||||
}
|
||||
|
||||
/** Called when the mutex is destroyed. */
|
||||
|
@ -230,8 +231,6 @@ public:
|
|||
latch_meta_t& meta = sync_latch_get_meta(m_id);
|
||||
|
||||
meta.get_counter()->single_deregister(&m_count);
|
||||
|
||||
sync_file_created_deregister(this);
|
||||
}
|
||||
|
||||
/** Called after a successful mutex acquire.
|
||||
|
@ -272,13 +271,21 @@ public:
|
|||
|
||||
/** @return the string representation */
|
||||
std::string to_string() const
|
||||
{ return sync_mutex_to_string(get_id(), sync_file_created_get(this)); }
|
||||
{
|
||||
return sync_mutex_to_string(get_id(),
|
||||
std::string(m_filename)
|
||||
.append(":")
|
||||
.append(std::to_string(m_line)));
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
MutexDebug<Mutex> context;
|
||||
#endif
|
||||
|
||||
private:
|
||||
const char *m_filename;
|
||||
uint32_t m_line;
|
||||
|
||||
/** The user visible counters, registered with the meta-data. */
|
||||
latch_meta_t::CounterType::Count m_count;
|
||||
|
||||
|
|
|
@ -567,6 +567,8 @@ struct rw_lock_t :
|
|||
#endif /* UNIV_DEBUG */
|
||||
public ilist_node<>
|
||||
{
|
||||
ut_d(bool created= false;)
|
||||
|
||||
/** Holds the state of the lock. */
|
||||
Atomic_relaxed<int32_t> lock_word;
|
||||
|
||||
|
|
|
@ -941,27 +941,6 @@ sync_latch_get_name(latch_level_t level);
|
|||
const char*
|
||||
sync_basename(const char* filename);
|
||||
|
||||
/** Register a latch, called when it is created
|
||||
@param[in] ptr Latch instance that was created
|
||||
@param[in] filename Filename where it was created
|
||||
@param[in] line Line number in filename */
|
||||
void
|
||||
sync_file_created_register(
|
||||
const void* ptr,
|
||||
const char* filename,
|
||||
uint16_t line);
|
||||
|
||||
/** Deregister a latch, called when it is destroyed
|
||||
@param[in] ptr Latch to be destroyed */
|
||||
void
|
||||
sync_file_created_deregister(const void* ptr);
|
||||
|
||||
/** Get the string where the file was created. Its format is "name:line"
|
||||
@param[in] ptr Latch instance
|
||||
@return created information or "" if can't be found */
|
||||
std::string
|
||||
sync_file_created_get(const void* ptr);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
|
||||
/** All (ordered) latches, used in debugging, must derive from this class. */
|
||||
|
|
|
@ -38,7 +38,7 @@ Created 2012-08-21 Sunny Bains
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
|
||||
|
@ -1506,173 +1506,6 @@ sync_latch_meta_destroy()
|
|||
latch_meta.clear();
|
||||
}
|
||||
|
||||
/** Track mutex file creation name and line number. This is to avoid storing
|
||||
{ const char* name; uint16_t line; } in every instance. This results in the
|
||||
sizeof(Mutex) > 64. We use a lookup table to store it separately. Fetching
|
||||
the values is very rare, only required for diagnostic purposes. And, we
|
||||
don't create/destroy mutexes that frequently. */
|
||||
struct CreateTracker {
|
||||
|
||||
/** Constructor */
|
||||
CreateTracker()
|
||||
UNIV_NOTHROW
|
||||
{
|
||||
m_mutex.init();
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
~CreateTracker()
|
||||
UNIV_NOTHROW
|
||||
{
|
||||
ut_ad(m_files.empty());
|
||||
|
||||
m_mutex.destroy();
|
||||
}
|
||||
|
||||
/** Register where the latch was created
|
||||
@param[in] ptr Latch instance
|
||||
@param[in] filename Where created
|
||||
@param[in] line Line number in filename */
|
||||
void register_latch(
|
||||
const void* ptr,
|
||||
const char* filename,
|
||||
uint16_t line)
|
||||
UNIV_NOTHROW
|
||||
{
|
||||
m_mutex.enter();
|
||||
|
||||
Files::iterator lb = m_files.lower_bound(ptr);
|
||||
|
||||
ut_ad(lb == m_files.end()
|
||||
|| m_files.key_comp()(ptr, lb->first));
|
||||
|
||||
typedef Files::value_type value_type;
|
||||
|
||||
m_files.insert(lb, value_type(ptr, File(filename, line)));
|
||||
|
||||
m_mutex.exit();
|
||||
}
|
||||
|
||||
/** Deregister a latch - when it is destroyed
|
||||
@param[in] ptr Latch instance being destroyed */
|
||||
void deregister_latch(const void* ptr)
|
||||
UNIV_NOTHROW
|
||||
{
|
||||
m_mutex.enter();
|
||||
|
||||
Files::iterator lb = m_files.lower_bound(ptr);
|
||||
|
||||
ut_ad(lb != m_files.end()
|
||||
&& !(m_files.key_comp()(ptr, lb->first)));
|
||||
|
||||
m_files.erase(lb);
|
||||
|
||||
m_mutex.exit();
|
||||
}
|
||||
|
||||
/** Get the create string, format is "name:line"
|
||||
@param[in] ptr Latch instance
|
||||
@return the create string or "" if not found */
|
||||
std::string get(const void* ptr)
|
||||
UNIV_NOTHROW
|
||||
{
|
||||
m_mutex.enter();
|
||||
|
||||
std::string created;
|
||||
|
||||
Files::iterator lb = m_files.lower_bound(ptr);
|
||||
|
||||
if (lb != m_files.end()
|
||||
&& !(m_files.key_comp()(ptr, lb->first))) {
|
||||
|
||||
std::ostringstream msg;
|
||||
|
||||
msg << lb->second.m_name << ":" << lb->second.m_line;
|
||||
|
||||
created = msg.str();
|
||||
}
|
||||
|
||||
m_mutex.exit();
|
||||
|
||||
return(created);
|
||||
}
|
||||
|
||||
private:
|
||||
/** For tracking the filename and line number */
|
||||
struct File {
|
||||
|
||||
/** Constructor */
|
||||
File() UNIV_NOTHROW : m_name(), m_line() { }
|
||||
|
||||
/** Constructor
|
||||
@param[in] name Filename where created
|
||||
@param[in] line Line number where created */
|
||||
File(const char* name, uint16_t line)
|
||||
UNIV_NOTHROW
|
||||
:
|
||||
m_name(sync_basename(name)),
|
||||
m_line(line)
|
||||
{
|
||||
/* No op */
|
||||
}
|
||||
|
||||
/** Filename where created */
|
||||
std::string m_name;
|
||||
|
||||
/** Line number where created */
|
||||
uint16_t m_line;
|
||||
};
|
||||
|
||||
/** Map the mutex instance to where it was created */
|
||||
typedef std::map<
|
||||
const void*,
|
||||
File,
|
||||
std::less<const void*>,
|
||||
ut_allocator<std::pair<const void* const, File> > >
|
||||
Files;
|
||||
|
||||
typedef OSMutex Mutex;
|
||||
|
||||
/** Mutex protecting m_files */
|
||||
Mutex m_mutex;
|
||||
|
||||
/** Track the latch creation */
|
||||
Files m_files;
|
||||
};
|
||||
|
||||
/** Track latch creation location. For reducing the size of the latches */
|
||||
static CreateTracker create_tracker;
|
||||
|
||||
/** Register a latch, called when it is created
|
||||
@param[in] ptr Latch instance that was created
|
||||
@param[in] filename Filename where it was created
|
||||
@param[in] line Line number in filename */
|
||||
void
|
||||
sync_file_created_register(
|
||||
const void* ptr,
|
||||
const char* filename,
|
||||
uint16_t line)
|
||||
{
|
||||
create_tracker.register_latch(ptr, filename, line);
|
||||
}
|
||||
|
||||
/** Deregister a latch, called when it is destroyed
|
||||
@param[in] ptr Latch to be destroyed */
|
||||
void
|
||||
sync_file_created_deregister(const void* ptr)
|
||||
{
|
||||
create_tracker.deregister_latch(ptr);
|
||||
}
|
||||
|
||||
/** Get the string where the file was created. Its format is "name:line"
|
||||
@param[in] ptr Latch instance
|
||||
@return created information or "" if can't be found */
|
||||
std::string
|
||||
sync_file_created_get(const void* ptr)
|
||||
{
|
||||
return(create_tracker.get(ptr));
|
||||
}
|
||||
|
||||
/** Initializes the synchronization data structures. */
|
||||
void
|
||||
sync_check_init()
|
||||
|
|
|
@ -234,6 +234,8 @@ rw_lock_create_func(
|
|||
|
||||
lock->is_block_lock = 0;
|
||||
|
||||
ut_d(lock->created = true);
|
||||
|
||||
mutex_enter(&rw_lock_list_mutex);
|
||||
rw_lock_list.push_front(*lock);
|
||||
mutex_exit(&rw_lock_list_mutex);
|
||||
|
@ -251,6 +253,8 @@ rw_lock_free_func(
|
|||
ut_ad(rw_lock_validate(lock));
|
||||
ut_a(lock->lock_word == X_LOCK_DECR);
|
||||
|
||||
ut_d(lock->created = false);
|
||||
|
||||
mutex_enter(&rw_lock_list_mutex);
|
||||
|
||||
os_event_destroy(lock->event);
|
||||
|
@ -850,6 +854,8 @@ rw_lock_validate(
|
|||
{
|
||||
ut_ad(lock);
|
||||
|
||||
ut_ad(lock->created);
|
||||
|
||||
int32_t lock_word = lock->lock_word;
|
||||
|
||||
ut_ad(lock->waiters < 2);
|
||||
|
|
Loading…
Reference in a new issue