From 0034da53788c470930743d9e5b64c9b4633e34a4 Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 21 Nov 2024 11:43:40 -0600 Subject: [PATCH] refactor: add in quorumBaseBlockIndexCache to reduce cs_main contention --- src/llmq/quorums.cpp | 15 ++++++++++++++- src/llmq/quorums.h | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 87aef8e79102a1..1b9902a5a8e2dd 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -633,7 +633,20 @@ std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const uint256& quorumHash) const { - const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(quorumHash)); + const CBlockIndex* pQuorumBaseBlockIndex = [&]() { + // Lock contention may still be high here; consider using a shared lock + // We cannot hold cs_quorumBaseBlockIndexCache the whole time as that creates lock-order inversion with cs_main; + // We cannot aquire cs_main if we have cs_quorumBaseBlockIndexCache held + const CBlockIndex* pindex; + if (!WITH_LOCK(cs_quorumBaseBlockIndexCache, return quorumBaseBlockIndexCache.get(quorumHash, pindex))) { + pindex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(quorumHash)); + if (pindex) { + LOCK(cs_quorumBaseBlockIndexCache); + quorumBaseBlockIndexCache.insert(quorumHash, pindex); + } + } + return pindex; + }(); if (!pQuorumBaseBlockIndex) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- block %s not found\n", __func__, quorumHash.ToString()); return nullptr; diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index fac31afb026bd5..4700bd6fc1dee0 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -252,6 +252,10 @@ class CQuorumManager mutable Mutex cs_cleanup; mutable std::map> cleanupQuorumsCache GUARDED_BY(cs_cleanup); + mutable Mutex cs_quorumBaseBlockIndexCache; + // On mainnet, we have around 62 quorums active at any point; let's cache a little more than double that to be safe. + mutable unordered_lru_cache quorumBaseBlockIndexCache; + mutable ctpl::thread_pool workerPool; mutable CThreadInterrupt quorumThreadInterrupt;