From 158d43a95055d96c172b059bd52fe74d9a71a752 Mon Sep 17 00:00:00 2001 From: cassandras-lies <203535133+cassandras-lies@users.noreply.github.com> Date: Thu, 23 Oct 2025 07:57:03 +0000 Subject: [PATCH 1/2] Stop copying vNodes dozens of times per second in CConnman::ThreadSocketHandler --- src/net.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 22ea040c82..4b044d6c34 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1358,27 +1358,34 @@ void CConnman::ThreadSocketHandler() // Disconnect nodes // { - LOCK(cs_vNodes); // Disconnect unused nodes - std::vector vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + LOCK(cs_vNodes); + + // Only copy nodes which are actually disconnected so as to minimise lock time. + std::vector vDisconnectedNodes; + BOOST_FOREACH(CNode* pnode, vNodes) { if (pnode->fDisconnect) { - // remove from vNodes - vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); + vDisconnectedNodes.push_back(pnode); + } + } - // release outbound grant (if any) - pnode->grantOutbound.Release(); - pnode->grantMasternodeOutbound.Release(); + BOOST_FOREACH(CNode* pnode, vDisconnectedNodes) + { + // remove from vNodes + vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); - // close socket and cleanup - pnode->CloseSocketDisconnect(); + // release outbound grant (if any) + pnode->grantOutbound.Release(); + pnode->grantMasternodeOutbound.Release(); - // hold in disconnected pool until all refs are released - pnode->Release(); - vNodesDisconnected.push_back(pnode); - } + // close socket and cleanup + pnode->CloseSocketDisconnect(); + + // hold in disconnected pool until all refs are released + pnode->Release(); + vNodesDisconnected.push_back(pnode); } } { From fbcf197b7e09e8cd47c82cda5cf8c4657a440656 Mon Sep 17 00:00:00 2001 From: cassandras-lies <203535133+cassandras-lies@users.noreply.github.com> Date: Tue, 14 Oct 2025 07:56:32 +0000 Subject: [PATCH 2/2] Make CSigSharesManager::WorkThreadMain run only every 1s rather than ever 100ms, and call RemoveBannedNodesStates() only once every 30s. This fixes near constant contention of cs_main. --- src/llmq/quorums_signing_shares.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 0815f5dd6c..f2cf3c79fb 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -1338,6 +1338,7 @@ void CSigSharesManager::BanNode(NodeId nodeId) void CSigSharesManager::WorkThreadMain() { int64_t lastSendTime = 0; + int64_t lastRemoveBannedNodeStatesTime = 0; while (!workInterrupt) { if (!quorumSigningManager || !g_connman) { @@ -1349,7 +1350,13 @@ void CSigSharesManager::WorkThreadMain() bool didWork = false; - RemoveBannedNodeStates(); + // RemoveBannedNodeStates holds cs_main, and its functionality is only required for local memory management. It + // is much more performant to call this rarely. + if (GetTimeMillis() - lastRemoveBannedNodeStatesTime > 30000 /* 30s */) { + RemoveBannedNodeStates(); + lastRemoveBannedNodeStatesTime = GetTimeMillis(); + } + didWork |= quorumSigningManager->ProcessPendingRecoveredSigs(*g_connman); didWork |= ProcessPendingSigShares(*g_connman); didWork |= SignPendingSigShares(); @@ -1364,7 +1371,7 @@ void CSigSharesManager::WorkThreadMain() // TODO Wakeup when pending signing is needed? if (!didWork) { - if (!workInterrupt.sleep_for(std::chrono::milliseconds(100))) { + if (!workInterrupt.sleep_for(std::chrono::milliseconds(1000))) { return; } }