From d947e259c9c89b766551c14dd99d5ac0e6e04931 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 23 Apr 2021 17:43:33 +0100 Subject: [PATCH] stack optimization - optimization of the multiqueue avoid notifying the consumer side of the multiqueue of a new pushed object, if the multiqueue already knows that the queue is not empty. --- lib/include/srsran/common/multiqueue.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/common/multiqueue.h b/lib/include/srsran/common/multiqueue.h index 3e1fe4f28..14130057f 100644 --- a/lib/include/srsran/common/multiqueue.h +++ b/lib/include/srsran/common/multiqueue.h @@ -72,7 +72,8 @@ class multiqueue_handler if (val == active_) { return; } - active_ = val; + active_ = val; + consumer_notify_needed = true; if (not active_) { buffer.clear(); @@ -112,10 +113,12 @@ class multiqueue_handler { std::unique_lock lock(q_mutex); if (buffer.empty()) { + consumer_notify_needed = true; return false; } obj = std::move(buffer.top()); buffer.pop(); + consumer_notify_needed = false; if (nof_waiting > 0) { lock.unlock(); cv_full.notify_one(); @@ -141,7 +144,14 @@ class multiqueue_handler } buffer.push(std::forward(*o)); } - parent->cv_empty.notify_one(); + if (consumer_notify_needed) { + // Note: The consumer thread only needs to be notified and awaken when queues transition from empty to non-empty + // To ensure that the consumer noticed that the queue was empty before a push, we store the last + // try_pop() return in a member variable. + // Doing this reduces the contention of multiple producers for the same condition variable + parent->cv_empty.notify_one(); + consumer_notify_needed = false; + } return true; } @@ -150,8 +160,9 @@ class multiqueue_handler mutable std::mutex q_mutex; srsran::dyn_circular_buffer buffer; std::condition_variable cv_full, cv_exit; - bool active_ = true; - int nof_waiting = 0; + bool active_ = true; + bool consumer_notify_needed = true; + int nof_waiting = 0; }; public: