Replace the std::stack member in the buffer_pool class for a vector to avoid reallocs.

master
faluco 4 years ago committed by faluco
parent 4c68c17bd3
commit 582ad5f6de

@ -48,7 +48,8 @@ public:
if (capacity_ > 0) { if (capacity_ > 0) {
nof_buffers = (uint32_t)capacity_; nof_buffers = (uint32_t)capacity_;
} }
used.reserve(nof_buffers); pool.reserve(nof_buffers);
free_list.reserve(nof_buffers);
pthread_mutex_init(&mutex, nullptr); pthread_mutex_init(&mutex, nullptr);
pthread_cond_init(&cv_not_empty, nullptr); pthread_cond_init(&cv_not_empty, nullptr);
for (uint32_t i = 0; i < nof_buffers; i++) { for (uint32_t i = 0; i < nof_buffers; i++) {
@ -57,21 +58,16 @@ public:
perror("Error allocating memory. Exiting...\n"); perror("Error allocating memory. Exiting...\n");
exit(-1); exit(-1);
} }
available.push(b); pool.push_back(b);
free_list.push_back(b);
} }
capacity = nof_buffers; capacity = nof_buffers;
} }
~buffer_pool() ~buffer_pool()
{ {
// this destructor assumes all buffers have been properly deallocated for (auto* p : pool) {
while (available.size()) { delete p;
delete available.top();
available.pop();
}
for (uint32_t i = 0; i < used.size(); i++) {
delete used[i];
} }
pthread_cond_destroy(&cv_not_empty); pthread_cond_destroy(&cv_not_empty);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
@ -79,11 +75,13 @@ public:
void print_all_buffers() void print_all_buffers()
{ {
printf("%d buffers in queue\n", (int)used.size()); printf("%d buffers in queue\n", static_cast<int>(pool.size() - free_list.size()));
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED #ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
std::map<std::string, uint32_t> buffer_cnt; std::map<std::string, uint32_t> buffer_cnt;
for (uint32_t i = 0; i < used.size(); i++) { for (uint32_t i = 0; i < pool.size(); i++) {
buffer_cnt[strlen(used[i]->debug_name) ? used[i]->debug_name : "Undefined"]++; if (std::find(free_list.cbegin(), free_list.cend(), pool[i]) == free_list.cend()) {
buffer_cnt[strlen(used[i]->debug_name) ? pool[i]->debug_name : "Undefined"]++;
}
} }
std::map<std::string, uint32_t>::iterator it; std::map<std::string, uint32_t>::iterator it;
for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) { for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) {
@ -92,22 +90,21 @@ public:
#endif #endif
} }
uint32_t nof_available_pdus() { return available.size(); } uint32_t nof_available_pdus() { return free_list.size(); }
bool is_almost_empty() { return available.size() < capacity / 20; } bool is_almost_empty() { return free_list.size() < capacity / 20; }
buffer_t* allocate(const char* debug_name = nullptr, bool blocking = false) buffer_t* allocate(const char* debug_name = nullptr, bool blocking = false)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
buffer_t* b = nullptr; buffer_t* b = nullptr;
if (available.size() > 0) { if (!free_list.empty()) {
b = available.top(); b = free_list.back();
used.push_back(b); free_list.pop_back();
available.pop();
if (is_almost_empty()) { if (is_almost_empty()) {
printf("Warning buffer pool capacity is %f %%\n", (float)100 * available.size() / capacity); printf("Warning buffer pool capacity is %f %%\n", (float)100 * free_list.size() / capacity);
} }
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED #ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
if (debug_name) { if (debug_name) {
@ -117,14 +114,13 @@ public:
#endif #endif
} else if (blocking) { } else if (blocking) {
// blocking allocation // blocking allocation
while (available.size() == 0) { while (free_list.empty()) {
pthread_cond_wait(&cv_not_empty, &mutex); pthread_cond_wait(&cv_not_empty, &mutex);
} }
// retrieve the new buffer // retrieve the new buffer
b = available.top(); b = free_list.back();
used.push_back(b); free_list.pop_back();
available.pop();
// do not print any warning // do not print any warning
} else { } else {
@ -143,10 +139,8 @@ public:
{ {
bool ret = false; bool ret = false;
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
typename std::vector<buffer_t*>::iterator elem = std::find(used.begin(), used.end(), b); if (std::find(pool.cbegin(), pool.cend(), b) != pool.cend()) {
if (elem != used.end()) { free_list.push_back(b);
used.erase(elem);
available.push(b);
ret = true; ret = true;
} }
pthread_cond_signal(&cv_not_empty); pthread_cond_signal(&cv_not_empty);
@ -156,8 +150,8 @@ public:
private: private:
static const int POOL_SIZE = 4096; static const int POOL_SIZE = 4096;
std::stack<buffer_t*> available; std::vector<buffer_t*> pool;
std::vector<buffer_t*> used; std::vector<buffer_t*> free_list;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cv_not_empty; pthread_cond_t cv_not_empty;
uint32_t capacity; uint32_t capacity;

Loading…
Cancel
Save