Merge bitcoin/bitcoin#23397: Avoid excessive lock contention in CCheckQueue::Add

459e208276 Exit early for an empty vChecks in CCheckQueue::Add (Hennadii Stepanov)
c43aa62343 Avoid excessive lock contention in CCheckQueue::Add (Hennadii Stepanov)

Pull request description:

  This PR significantly reduces lock contention in the `CCheckQueue` class by releasing a mutex before calling `std::condition_variable::notify_one` and `std::condition_variable::notify_all`.

  From C++ [docs](https://en.cppreference.com/w/cpp/thread/condition_variable/notify_one):
  > The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); in fact doing so is a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock.

  Related to:
  - #23167
  - #23223

ACKs for top commit:
  martinus:
    ACK 459e208, codereview and tested. I first thought this introduced a segfault in `psbt_wallet_tests/psbt_updater_test` because that test failed for me, but thats a different issue fixed in #23403.
  vasild:
    ACK 459e208276
  theStack:
    Code-review ACK 459e208276

Tree-SHA512: c197858656392ba3ebcd638d713cf93c9fb48b7b3bad193209490d2828f9c7e3ae4dee6f84674f2f34dceed894139562e29579ee7299e06756c8c990caddc5ed
This commit is contained in:
MarcoFalke 2021-11-29 11:02:41 +01:00
commit b4f647fa36
No known key found for this signature in database
GPG Key ID: CE2B75697E69A548

View File

@ -167,16 +167,24 @@ public:
//! Add a batch of checks to the queue
void Add(std::vector<T>& vChecks)
{
LOCK(m_mutex);
for (T& check : vChecks) {
queue.push_back(T());
check.swap(queue.back());
if (vChecks.empty()) {
return;
}
nTodo += vChecks.size();
if (vChecks.size() == 1)
{
LOCK(m_mutex);
for (T& check : vChecks) {
queue.emplace_back();
check.swap(queue.back());
}
nTodo += vChecks.size();
}
if (vChecks.size() == 1) {
m_worker_cv.notify_one();
else if (vChecks.size() > 1)
} else {
m_worker_cv.notify_all();
}
}
//! Stop all of the worker threads.