-
Notifications
You must be signed in to change notification settings - Fork 1.2k
perf: reduce amount of used memory and threads #7659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
f36e5e2
a739cf7
756fc4f
e4f459d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,6 @@ | |
| #include <chainparams.h> | ||
| #include <dbwrapper.h> | ||
| #include <logging.h> | ||
| #include <util/thread.h> | ||
| #include <util/time.h> | ||
| #include <validation.h> | ||
|
|
||
|
|
@@ -40,18 +39,10 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& | |
| db{util::MakeDbWrapper({db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})} | ||
| { | ||
| mapQuorumsCache.Init(m_chainman.GetConsensus(), /*limit_by_connections=*/false); | ||
| m_cache_interrupt.reset(); | ||
| m_cache_thread = std::thread(&util::TraceThread, "q-cache", [this] { CacheWarmingThreadMain(); }); | ||
| MigrateOldQuorumDB(_evoDb); | ||
| } | ||
|
|
||
| CQuorumManager::~CQuorumManager() | ||
| { | ||
| if (m_cache_thread.joinable()) { | ||
| m_cache_interrupt(); | ||
| m_cache_thread.join(); | ||
| } | ||
| } | ||
| CQuorumManager::~CQuorumManager() = default; | ||
|
|
||
| bool CQuorumManager::GetEncryptedContributions(Consensus::LLMQType llmq_type, const CBlockIndex* block_index, | ||
| const std::vector<bool>& valid_members, const uint256& protx_hash, | ||
|
|
@@ -505,50 +496,29 @@ void CQuorumManager::WriteContributions(const CQuorumPtr& quorum) const | |
| quorum->WriteContributions(*db); | ||
| } | ||
|
|
||
| void CQuorumManager::CacheWarmingThreadMain() const | ||
| void CQuorumManager::QueueQuorumForWarming(CQuorumCPtr pQuorum) const | ||
| { | ||
| while (!m_cache_interrupt) { | ||
| CQuorumCPtr pQuorum; | ||
| { | ||
| LOCK(m_cache_cs); | ||
| if (!m_cache_queue.empty()) { | ||
| pQuorum = std::move(m_cache_queue.front()); | ||
| m_cache_queue.pop_front(); | ||
| }; | ||
| } | ||
|
|
||
| if (!pQuorum) { | ||
| m_cache_interrupt.sleep_for(std::chrono::milliseconds(100)); | ||
| continue; | ||
| } | ||
|
|
||
| if (!pQuorum->HasVerificationVector()) { | ||
| return; | ||
| } | ||
| // The job may reference this manager: ~LLMQContext stops the worker pool before destroying it. | ||
| blsWorker.PushJob([this, pQuorum = std::move(pQuorum)]() { | ||
| cxxtimer::Timer t(true); | ||
| LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- type=%d height=%d hash=%s start\n", __func__, | ||
| LogPrint(BCLog::LLMQ, "CQuorumManager::QueueQuorumForWarming -- type=%d height=%d hash=%s start\n", | ||
| std23::to_underlying(pQuorum->params.type), pQuorum->m_quorum_base_block_index->nHeight, | ||
| pQuorum->m_quorum_base_block_index->GetBlockHash().ToString()); | ||
|
|
||
| // when then later some other thread tries to get keys, it will be much faster | ||
| for (const auto i : util::irange(pQuorum->members.size())) { | ||
| if (m_cache_interrupt) { | ||
| break; | ||
| if (m_warming_interrupted) { | ||
| return; | ||
| } | ||
| if (pQuorum->qc->validMembers[i]) { | ||
| pQuorum->GetPubKeyShare(i); | ||
|
Comment on lines
510
to
515
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Let required BLS work run between bounded warming batches This loop occupies one BLS worker until every valid member's public-key share has been computed. DEFAULT_WORKER_COUNT is one on a two-logical-CPU host, and the pool uses a FIFO queue with no priority or interleaving within a job. NetQuorum::ProcessContribQDATA() calls AggregateSecretKeys() synchronously at net_quorum.cpp:345; that function submits aggregation to this same pool and waits on its future. Consequently, warming another quorum blocks recovery and the P2P message-processing thread even when the recovering quorum already has its verification vector. This affects ordinary masternodes, not just -watchquorums, and a 400-member quorum with a 340-coefficient verification vector entails substantial share-computation work before the worker becomes available. Additional queued warmers extend the delay. The former dedicated warming thread did not impose this queue dependency. Split warming into small resumable batches and bound outstanding warming work so required aggregation and DKG jobs can interleave, with a single-worker regression test. source: ['claude'] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Withdrawn (re-reviewed at |
||
| } | ||
| } | ||
|
|
||
| LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- type=%d height=%d hash=%s done. time=%d\n", __func__, | ||
| LogPrint(BCLog::LLMQ, "CQuorumManager::QueueQuorumForWarming -- type=%d height=%d hash=%s done. time=%d\n", | ||
| std23::to_underlying(pQuorum->params.type), pQuorum->m_quorum_base_block_index->nHeight, | ||
| pQuorum->m_quorum_base_block_index->GetBlockHash().ToString(), t.count()); | ||
| } | ||
| } | ||
|
|
||
| void CQuorumManager::QueueQuorumForWarming(CQuorumCPtr pQuorum) const | ||
| { | ||
| if (pQuorum->HasVerificationVector()) { | ||
| LOCK(m_cache_cs); | ||
| m_cache_queue.push_back(std::move(pQuorum)); | ||
| } | ||
| }); | ||
|
Comment on lines
+505
to
+521
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Bound background warming on the shared BLS pool Each quorum now contributes one job that computes every valid member's public-key share on the same 1–4-thread FIFO source: ['claude', 'codex']
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validation logic is unchanged compare to develop, only its own thread is gone. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still applies (re-reviewed at |
||
| } | ||
|
|
||
| // TODO: remove in v23 | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -114,6 +114,13 @@ def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timew | |||||||||||||||||||||||||||||||
| "-debugexclude=leveldb", | ||||||||||||||||||||||||||||||||
| "-debugexclude=rand", | ||||||||||||||||||||||||||||||||
| "-uacomment=testnode%d" % i, # required for subversion uniqueness across peers | ||||||||||||||||||||||||||||||||
| # Two threads keep the check queues and the RPC server concurrent; more only adds | ||||||||||||||||||||||||||||||||
| # threads, and every thread costs ~0.9 MB of thread-local storage (BLS context). | ||||||||||||||||||||||||||||||||
| "-par=2", | ||||||||||||||||||||||||||||||||
| "-rpcthreads=2", | ||||||||||||||||||||||||||||||||
| # The signature and script execution caches are allocated and zero-filled at startup | ||||||||||||||||||||||||||||||||
| # whether or not anything is ever cached; 1 MiB still leaves 16384 entries each. | ||||||||||||||||||||||||||||||||
| "-maxsigcachesize=1", | ||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||
|
Comment on lines
+119
to
124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Gate -parbls for pre-v23 test binaries
Suggested change
source: ['claude'] |
||||||||||||||||||||||||||||||||
| if self.mocktime != 0: | ||||||||||||||||||||||||||||||||
| self.args.append(f"-mocktime={mocktime}") | ||||||||||||||||||||||||||||||||
|
|
@@ -138,6 +145,8 @@ def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timew | |||||||||||||||||||||||||||||||
| self.args.append("-logsourcelocations") | ||||||||||||||||||||||||||||||||
| if self.version_is_at_least(22010000): | ||||||||||||||||||||||||||||||||
| self.args.append("-loglevel=trace") | ||||||||||||||||||||||||||||||||
| if self.version_is_at_least(23000000): | ||||||||||||||||||||||||||||||||
| self.args.append("-parbls=2") | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Default behavior from global -v2transport flag is added to args to persist it over restarts. | ||||||||||||||||||||||||||||||||
| # May be overwritten in individual tests, using extra_args. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a watcher loads many verification vectors, each quorum adds a long-running warming job to the same FIFO
CBLSWorkerpool used byAsyncVerifySig; scans can populate up to 64 quorums, so signature, ChainLock, and InstantSend verification submitted afterward cannot run until all earlier warmers finish. The former dedicated thread kept warming off the latency-sensitive verification pool; retain a single outstanding warming task or otherwise prioritize verification work.AGENTS.md reference: AGENTS.md:L211-L212
Useful? React with 👍 / 👎.