Make worker-local data lookups faster
By using a std::vector to store the keys, the cost of key lookup goes down in comparison with std::unordered_map. The downside is the increase in memory use in certain situations but given the fact that the intended purpose of worker-local data is to store global data, this is unlikely to have observable negative side-effects. Depending on the implementations of std::vector and std::unordered_map, the use of std::vector could even result in a smaller memory footprint.
This commit is contained in:
@ -185,8 +185,8 @@ public:
|
|||||||
typedef Registry<MXS_SESSION> SessionsById;
|
typedef Registry<MXS_SESSION> SessionsById;
|
||||||
typedef std::vector<DCB*> Zombies;
|
typedef std::vector<DCB*> Zombies;
|
||||||
|
|
||||||
typedef std::unordered_map<uint64_t, void*> LocalData;
|
typedef std::vector<void*> LocalData;
|
||||||
typedef std::unordered_map<uint64_t, void (*)(void*)> DataDeleters;
|
typedef std::vector<void (*)(void*)> DataDeleters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the routing worker mechanism.
|
* Initialize the routing worker mechanism.
|
||||||
@ -475,8 +475,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
static uint64_t create_key()
|
static uint64_t create_key()
|
||||||
{
|
{
|
||||||
static uint64_t id_generator = 0;
|
static std::atomic<uint64_t> id_generator {0};
|
||||||
return mxb::atomic::add(&id_generator, 1, mxb::atomic::RELAXED);
|
return id_generator.fetch_add(1, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -487,6 +487,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
void set_data(uint64_t key, void* data, void (* callback)(void*))
|
void set_data(uint64_t key, void* data, void (* callback)(void*))
|
||||||
{
|
{
|
||||||
|
if (m_local_data.size() <= key)
|
||||||
|
{
|
||||||
|
m_local_data.resize(key + 1, nullptr);
|
||||||
|
m_data_deleters.resize(key + 1, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (callback)
|
if (callback)
|
||||||
{
|
{
|
||||||
m_data_deleters[key] = callback;
|
m_data_deleters[key] = callback;
|
||||||
@ -502,10 +508,9 @@ public:
|
|||||||
*
|
*
|
||||||
* @return Data previously stored
|
* @return Data previously stored
|
||||||
*/
|
*/
|
||||||
void* get_data(uint64_t key)
|
void* get_data(uint64_t key) const
|
||||||
{
|
{
|
||||||
auto it = m_local_data.find(key);
|
return key < m_local_data.size() ? m_local_data[key] : nullptr;
|
||||||
return it != m_local_data.end() ? it->second : NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -517,19 +522,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
void delete_data(uint64_t key)
|
void delete_data(uint64_t key)
|
||||||
{
|
{
|
||||||
auto data = m_local_data.find(key);
|
if (key < m_local_data.size())
|
||||||
|
|
||||||
if (data != m_local_data.end())
|
|
||||||
{
|
{
|
||||||
auto deleter = m_data_deleters.find(key);
|
if (auto deleter = m_data_deleters[key])
|
||||||
|
|
||||||
if (deleter != m_data_deleters.end())
|
|
||||||
{
|
{
|
||||||
deleter->second(data->second);
|
deleter(m_local_data[key]);
|
||||||
m_data_deleters.erase(deleter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_local_data.erase(data);
|
m_data_deleters[key] = nullptr;
|
||||||
|
m_local_data[key] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,7 +767,8 @@ private:
|
|||||||
|
|
||||||
T* get_local_value() const
|
T* get_local_value() const
|
||||||
{
|
{
|
||||||
T* my_value = static_cast<T*>(mxs_rworker_get_data(m_handle));
|
auto worker = RoutingWorker::get_current();
|
||||||
|
T* my_value = static_cast<T*>(worker->get_data(m_handle));
|
||||||
|
|
||||||
if (my_value == nullptr)
|
if (my_value == nullptr)
|
||||||
{
|
{
|
||||||
@ -775,7 +777,7 @@ private:
|
|||||||
my_value = new T(m_value);
|
my_value = new T(m_value);
|
||||||
guard.unlock();
|
guard.unlock();
|
||||||
|
|
||||||
mxs_rworker_set_data(m_handle, my_value, destroy_value);
|
worker->set_data(m_handle, my_value, destroy_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
mxb_assert(my_value);
|
mxb_assert(my_value);
|
||||||
|
|||||||
Reference in New Issue
Block a user