Skip to content

Commit

Permalink
Perf[BMQ,MQB]: resource manager for per-thread resources
Browse files Browse the repository at this point in the history
Signed-off-by: Evgeny Malygin <[email protected]>
  • Loading branch information
678098 committed Nov 4, 2024
1 parent 461d06f commit 7ed3266
Show file tree
Hide file tree
Showing 21 changed files with 501 additions and 202 deletions.
25 changes: 20 additions & 5 deletions src/groups/bmq/bmqu/bmqu_resourcemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ namespace bmqu {

ResourceManager *ResourceManager::g_instance_p = 0;

ResourceManager::ThreadResources::~ThreadResources()
{
for (size_t i = 0; i < d_resources.size(); i++) {
if (d_resources.at(i).numReferences() > 1) {
BALL_LOG_ERROR
<< "Resource " << d_resources.at(i).numReferences()
<< " references "
<< "will not be freed, something holds onto this resource";
}
}

// Free resources in the reversed order of how they were registered
while (!d_resources.empty()) {
d_resources.pop_back();
}
}

ResourceManager::ResourceManager(bslma::Allocator* allocator)
: d_allocator_p(allocator)
Expand All @@ -40,11 +56,10 @@ ResourceManager::~ResourceManager() {
<< "will not be freed";
}
}
for (size_t i = 0; i < d_resources.size(); i++) {
if (d_resources.at(i).numReferences() > 1) {
BALL_LOG_ERROR << "Resource " << d_resourceCreators.at(i).numReferences() << " references "
<< "will not be freed, something holds onto this resource";
}

// Free resources in the reversed order of how they were registered
while (!d_resourceCreators.empty()) {
d_resourceCreators.pop_back();
}
}

Expand Down
105 changes: 81 additions & 24 deletions src/groups/bmq/bmqu/bmqu_resourcemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@
// TBD:

// BDE
#include <bslmt_threadutil.h>
#include <bslmt_mutex.h>
#include <bslmt_lockguard.h>
#include <bsl_vector.h>
#include <bsl_memory.h>
#include <bsl_functional.h>
#include <bsl_memory.h>
#include <bsl_unordered_map.h>
#include <bsl_vector.h>
#include <bslmt_lockguard.h>
#include <bslmt_mutex.h>
#include <bslmt_once.h>
#include <bslmt_threadutil.h>
#include <bsls_assert.h>
#include <bsls_performancehint.h>
#include <bsls_types.h>
Expand Down Expand Up @@ -81,9 +82,26 @@ class ResourceManager {
};

struct ThreadResources {

// TRAITS
BSLMF_NESTED_TRAIT_DECLARATION(ThreadResources,
bslma::UsesBslmaAllocator)

// DATA
bsl::vector<bsl::shared_ptr<void> > d_resources;

explicit ThreadResources(bslma::Allocator* allocator)
: d_resources(allocator)
{
// NOTHING
}

~ThreadResources();
};

typedef bsl::unordered_map<bsls::Types::Uint64,
bsl::shared_ptr<ThreadResources> >
ThreadIdToResourcesMap;

// CLASS DATA
static ResourceManager *g_instance_p;

Expand All @@ -93,22 +111,24 @@ class ResourceManager {
bslmt::Mutex d_mutex;

bsl::vector<bsl::shared_ptr<void> > d_resourceCreators;
bsl::vector<bsl::shared_ptr<void> > d_resources;

ThreadIdToResourcesMap d_resources;

private:
// CREATORS
explicit ResourceManager(bslma::Allocator* allocator = 0);
~ResourceManager();

// PRIVATE CLASS METHODS

static unsigned int nextTypeId();

public:
// TYPES
// TRAITS
BSLMF_NESTED_TRAIT_DECLARATION(ResourceManager, bslma::UsesBslmaAllocator)

public:
// CREATORS
~ResourceManager();

// PUBLIC CLASS METHODS
static void init(bslma::Allocator* allocator);
Expand All @@ -124,16 +144,11 @@ class ResourceManager {

size_t typeId = Traits::typeId();

BALL_LOG_ERROR << typeId;

bslmt::LockGuard<bslmt::Mutex> guard(&manager.d_mutex);

if (manager.d_resourceCreators.size() <= typeId) {
manager.d_resourceCreators.resize(typeId + 1);
}
if (manager.d_resources.size() <= typeId) {
manager.d_resources.resize(typeId + 1);
}
BSLS_ASSERT_OPT(!manager.d_resourceCreators.at(typeId));

typename Traits::factory_pointer_type creator_sp;
Expand All @@ -150,21 +165,63 @@ class ResourceManager {

typedef ResourceTraits<TYPE> Traits;

size_t typeId = Traits::typeId();
const size_t typeId = Traits::typeId();
bsls::Types::Uint64 threadId = bslmt::ThreadUtil::selfIdAsUint64();

ThreadResources* resources = NULL;

{
bslmt::LockGuard<bslmt::Mutex> guard(&manager.d_mutex); // LOCK

ThreadIdToResourcesMap::iterator it = manager.d_resources.find(
threadId);
if (it == manager.d_resources.end()) {
bsl::pair<ThreadIdToResourcesMap::iterator, bool> res =
manager.d_resources.emplace(
threadId,
bsl::make_shared<ThreadResources>(
manager.d_allocator_p));
resources = res.first->second.get();
}
else {
resources = it->second.get();
}
}
BSLS_ASSERT_SAFE(resources);
// Now we work with `resources` exclusively assigned to this thread.
// Can modify this object without synchronizations.

bslmt::LockGuard<bslmt::Mutex> guard(&manager.d_mutex);

if (manager.d_resources.at(typeId)) {
return bsl::reinterpret_pointer_cast<TYPE>(manager.d_resources.at(typeId));
if (resources->d_resources.size() <= typeId) {
resources->d_resources.resize(typeId + 1);
}

if (resources->d_resources.at(typeId)) {
return bsl::reinterpret_pointer_cast<TYPE>(
resources->d_resources.at(typeId)); // RETURN
}

BSLS_ASSERT_OPT(manager.d_resourceCreators.at(typeId) && "Resource factory for the resource is not registered");
typename Traits::factory_type* creator = NULL;
{
bslmt::LockGuard<bslmt::Mutex> guard(&manager.d_mutex); // LOCK

// Need to make this check under mutex, since `d_resourceCreators`
// might be modified at the same time.
BSLS_ASSERT_OPT(
manager.d_resourceCreators.at(typeId) &&
"Resource factory for the resource is not registered");

creator =
bsl::reinterpret_pointer_cast<typename Traits::factory_type>(
manager.d_resourceCreators.at(typeId))
.get();
}
BSLS_ASSERT_SAFE(creator);

const typename Traits::factory_type &creator =
*bsl::reinterpret_pointer_cast<typename Traits::factory_type >(manager.d_resourceCreators.at(typeId));
typename Traits::pointer_type resource = (*creator)(
manager.d_allocator_p);

typename Traits::pointer_type resource(creator(manager.d_allocator_p));
manager.d_resources.at(typeId) = resource;
// Store as a `void` shared pointer in the common collection.
resources->d_resources.at(typeId) = resource;
return resource;
}

Expand Down
Loading

0 comments on commit 7ed3266

Please sign in to comment.