common/Finisher: avoid memory re-allocations for finisher queue

Since there is only a single thread associated with the Finisher,
swap between two queues to avoid the need to re-allocate a new
vector for each iteration through the loop. Also replace the
condition broadcast with a signal since there is only a single
thread to wake up.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2019-05-08 14:09:17 -04:00
parent 99826fbe75
commit cc7ec3e18d
2 changed files with 12 additions and 10 deletions

View File

@ -51,23 +51,23 @@ void *Finisher::finisher_thread_entry()
// To reduce lock contention, we swap out the queue to process.
// This way other threads can submit new contexts to complete
// while we are working.
vector<pair<Context*,int>> ls;
ls.swap(finisher_queue);
in_progress_queue.swap(finisher_queue);
finisher_running = true;
ul.unlock();
ldout(cct, 10) << "finisher_thread doing " << ls << dendl;
ldout(cct, 10) << "finisher_thread doing " << in_progress_queue << dendl;
if (logger) {
start = ceph_clock_now();
count = ls.size();
count = in_progress_queue.size();
}
// Now actually process the contexts.
for (auto p : ls) {
for (auto p : in_progress_queue) {
p.first->complete(p.second);
}
ldout(cct, 10) << "finisher_thread done with " << ls << dendl;
ls.clear();
ldout(cct, 10) << "finisher_thread done with " << in_progress_queue
<< dendl;
in_progress_queue.clear();
if (logger) {
logger->dec(l_finisher_queue_len, count);
logger->tinc(l_finisher_complete_lat, ceph_clock_now() - start);

View File

@ -47,6 +47,7 @@ class Finisher {
/// Queue for contexts for which complete(0) will be called.
std::vector<std::pair<Context*,int>> finisher_queue;
std::vector<std::pair<Context*,int>> in_progress_queue;
std::string thread_name;
@ -66,10 +67,11 @@ class Finisher {
/// Add a context to complete, optionally specifying a parameter for the complete function.
void queue(Context *c, int r = 0) {
std::unique_lock ul(finisher_lock);
if (finisher_queue.empty()) {
finisher_cond.notify_all();
}
bool was_empty = finisher_queue.empty();
finisher_queue.push_back(std::make_pair(c, r));
if (was_empty) {
finisher_cond.notify_one();
}
if (logger)
logger->inc(l_finisher_queue_len);
}