Skip to content

Commit 319e6ea

Browse files
perf: use unordered_set / unordered_map where order isn't relevant
Did a few quickbench to ensure there isn't some advantage to using the "worse" data structure at small sizes. set: https://quick-bench.com/q/ApPAGguzG2F9AnqM2GkgDAXCzX4 map: https://quick-bench.com/q/PXDdF0HVGpiSmC9Hh5FUSTp0uJU Using unordered_map did show a tiny insertion regression for ~expected sizes on masternodes, but it appears that only 1 access will compensate for that overhead, and each su, some perf results I have are here, show that this std::set usage is causing an imo unacceptably high cpu usage. ``` - 9.18% 0.00% d-mncon dashd [.] CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&)::{lambda()#▒ - CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&)::{lambda()#1}::operator()() const ▒ + 6.16% CConnman::IsMasternodeOrDisconnectRequested(CService const&) ▒ - 2.66% std::set<CService, std::less<CService>, std::allocator<CService> >::count(CService const&) const ▒ - std::_Rb_tree<CService, CService, std::_Identity<CService>, std::less<CService>, std::allocator<CService> >::find(CService const&) const ▒ - 2.02% std::_Rb_tree<CService, CService, std::_Identity<CService>, std::less<CService>, std::allocator<CService> >::_M_lower_bound(std::_Rb_tree_node<CService> const▒ + 1.99% std::less<CService>::operator()(CService const&, CService const&) const ▒ + 0.62% std::less<CService>::operator()(CService const&, CService const&) const ```
1 parent dd96032 commit 319e6ea

File tree

7 files changed

+36
-33
lines changed

7 files changed

+36
-33
lines changed

src/llmq/dkgsession.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
#include <bls/bls_worker.h>
1414
#include <sync.h>
1515
#include <util/underlying.h>
16+
#include <saltedhasher.h>
1617

1718
#include <optional>
19+
#include <unordered_set>
1820

1921
class CActiveMasternodeManager;
2022
class CInv;
@@ -293,7 +295,7 @@ class CDKGSession
293295
private:
294296
std::vector<std::unique_ptr<CDKGMember>> members;
295297
std::map<uint256, size_t> membersMap;
296-
std::set<uint256> relayMembers;
298+
std::unordered_set<uint256, StaticSaltedHasher> relayMembers;
297299
BLSVerificationVectorPtr vvecContribution;
298300
std::vector<CBLSSecretKey> m_sk_contributions;
299301

@@ -382,7 +384,7 @@ class CDKGSession
382384

383385
public:
384386
[[nodiscard]] CDKGMember* GetMember(const uint256& proTxHash) const;
385-
[[nodiscard]] const std::set<uint256>& RelayMembers() const { return relayMembers; }
387+
[[nodiscard]] const std::unordered_set<uint256, StaticSaltedHasher>& RelayMembers() const { return relayMembers; }
386388
[[nodiscard]] const CBlockIndex* BlockIndex() const { return m_quorum_base_block_index; }
387389
[[nodiscard]] const uint256& ProTx() const { return myProTxHash; }
388390
[[nodiscard]] const Consensus::LLMQParams GetParams() const { return params; }

src/llmq/quorums.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus::
370370
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
371371
}
372372
} else if (watchOtherISQuorums && !quorum->IsMember(myProTxHash)) {
373-
std::set<uint256> connections;
373+
std::unordered_set<uint256, StaticSaltedHasher> connections;
374374
const auto& cindexes = utils::CalcDeterministicWatchConnections(llmqParams.type, quorum->m_quorum_base_block_index, quorum->members.size(), 1);
375375
for (auto idx : cindexes) {
376376
connections.emplace(quorum->members[idx]->proTxHash);

src/llmq/signing_shares.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ void CSigSharesManager::ProcessSigShare(PeerManager& peerman, const CSigShare& s
717717
bool canTryRecovery = false;
718718

719719
// prepare node set for direct-push in case this is our sig share
720-
std::set<NodeId> quorumNodes;
720+
std::unordered_set<NodeId> quorumNodes;
721721
if (!IsAllMembersConnectedEnabled(llmqType, m_sporkman) && sigShare.getQuorumMember() == quorum->GetMemberIndex(m_mn_activeman->GetProTxHash())) {
722722
quorumNodes = connman.GetMasternodeQuorumNodes(sigShare.getLlmqType(), sigShare.getQuorumHash());
723723
}

src/llmq/utils.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -653,12 +653,12 @@ uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256
653653
return proTxHash2;
654654
}
655655

656-
std::set<uint256> GetQuorumConnections(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman,
656+
std::unordered_set<uint256, StaticSaltedHasher> GetQuorumConnections(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman,
657657
gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound)
658658
{
659659
if (IsAllMembersConnectedEnabled(llmqParams.type, sporkman)) {
660660
auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex);
661-
std::set<uint256> result;
661+
std::unordered_set<uint256, StaticSaltedHasher> result;
662662

663663
for (const auto& dmn : mns) {
664664
if (dmn->proTxHash == forMember) {
@@ -677,23 +677,23 @@ std::set<uint256> GetQuorumConnections(const Consensus::LLMQParams& llmqParams,
677677
return GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, forMember, onlyOutbound);
678678
}
679679

680-
std::set<uint256> GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex,
680+
std::unordered_set<uint256, StaticSaltedHasher> GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex,
681681
const uint256& forMember, bool onlyOutbound)
682682
{
683683
auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex);
684-
std::set<uint256> result;
684+
std::unordered_set<uint256, StaticSaltedHasher> result;
685685

686686
auto calcOutbound = [&](size_t i, const uint256& proTxHash) {
687+
// Relay to nodes at indexes (i+2^k)%n, where
688+
// k: 0..max(1, floor(log2(n-1))-1)
689+
// n: size of the quorum/ring
690+
std::unordered_set<uint256, StaticSaltedHasher> r{};
687691
if (mns.size() == 1) {
688692
// No outbound connections are needed when there is one MN only.
689693
// Also note that trying to calculate results via the algorithm below
690694
// would result in an endless loop.
691-
return std::set<uint256>();
695+
return r;
692696
}
693-
// Relay to nodes at indexes (i+2^k)%n, where
694-
// k: 0..max(1, floor(log2(n-1))-1)
695-
// n: size of the quorum/ring
696-
std::set<uint256> r;
697697
int gap = 1;
698698
int gap_max = (int)mns.size() - 1;
699699
int k = 0;
@@ -775,8 +775,8 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman&
775775
LogPrint(BCLog::NET_NETCONN, "%s -- isMember=%d for quorum %s:\n",
776776
__func__, isMember, pQuorumBaseBlockIndex->GetBlockHash().ToString());
777777

778-
std::set<uint256> connections;
779-
std::set<uint256> relayMembers;
778+
std::unordered_set<uint256, StaticSaltedHasher> connections;
779+
std::unordered_set<uint256, StaticSaltedHasher> relayMembers;
780780
if (isMember) {
781781
connections = GetQuorumConnections(llmqParams, dmnman, sporkman, pQuorumBaseBlockIndex, myProTxHash, true);
782782
relayMembers = GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, myProTxHash, true);

src/llmq/utils.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
#include <sync.h>
1010
#include <gsl/pointers.h>
1111
#include <uint256.h>
12+
#include <saltedhasher.h>
1213

1314
#include <map>
1415
#include <set>
1516
#include <vector>
17+
#include <unordered_set>
1618

1719
class CConnman;
1820
class CBlockIndex;
@@ -34,8 +36,8 @@ namespace utils
3436
std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, bool reset_cache = false);
3537

3638
uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256& proTxHash2);
37-
std::set<uint256> GetQuorumConnections(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound);
38-
std::set<uint256> GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound);
39+
std::unordered_set<uint256, StaticSaltedHasher> GetQuorumConnections(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound);
40+
std::unordered_set<uint256, StaticSaltedHasher> GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound);
3941
std::set<size_t> CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, size_t memberCount, size_t connectionCount);
4042

4143
bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, const CSporkManager& sporkman,

src/net.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,12 +3718,11 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
37183718

37193719
if (!fNetworkActive || !m_masternode_thread_active || !mn_sync.IsBlockchainSynced()) continue;
37203720

3721-
std::set<CService> connectedNodes;
3722-
std::map<uint256 /*proTxHash*/, bool /*fInbound*/> connectedProRegTxHashes;
3721+
std::unordered_set<CService, CServiceHash> connectedNodes;
3722+
std::unordered_map<uint256 /*proTxHash*/, bool /*fInbound*/, StaticSaltedHasher> connectedProRegTxHashes;
37233723
ForEachNode([&](const CNode* pnode) {
3724-
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
37253724
connectedNodes.emplace(pnode->addr);
3726-
if (!verifiedProRegTxHash.IsNull()) {
3725+
if (auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash(); !verifiedProRegTxHash.IsNull()) {
37273726
connectedProRegTxHashes.emplace(verifiedProRegTxHash, pnode->IsInboundConn());
37283727
}
37293728
});
@@ -4617,7 +4616,7 @@ bool CConnman::AddPendingMasternode(const uint256& proTxHash)
46174616
return true;
46184617
}
46194618

4620-
void CConnman::SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes)
4619+
void CConnman::SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::unordered_set<uint256, StaticSaltedHasher>& proTxHashes)
46214620
{
46224621
LOCK(cs_vPendingMasternodes);
46234622
auto it = masternodeQuorumNodes.emplace(std::make_pair(llmqType, quorumHash), proTxHashes);
@@ -4626,7 +4625,7 @@ void CConnman::SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint
46264625
}
46274626
}
46284627

4629-
void CConnman::SetMasternodeQuorumRelayMembers(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes)
4628+
void CConnman::SetMasternodeQuorumRelayMembers(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::unordered_set<uint256, StaticSaltedHasher>& proTxHashes)
46304629
{
46314630
{
46324631
LOCK(cs_vPendingMasternodes);
@@ -4657,10 +4656,10 @@ bool CConnman::HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint
46574656
return masternodeQuorumNodes.count(std::make_pair(llmqType, quorumHash));
46584657
}
46594658

4660-
std::set<uint256> CConnman::GetMasternodeQuorums(Consensus::LLMQType llmqType) const
4659+
std::unordered_set<uint256, StaticSaltedHasher> CConnman::GetMasternodeQuorums(Consensus::LLMQType llmqType) const
46614660
{
46624661
LOCK(cs_vPendingMasternodes);
4663-
std::set<uint256> result;
4662+
std::unordered_set<uint256, StaticSaltedHasher> result;
46644663
for (const auto& p : masternodeQuorumNodes) {
46654664
if (p.first.first != llmqType) {
46664665
continue;
@@ -4670,7 +4669,7 @@ std::set<uint256> CConnman::GetMasternodeQuorums(Consensus::LLMQType llmqType) c
46704669
return result;
46714670
}
46724671

4673-
std::set<NodeId> CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const
4672+
std::unordered_set<NodeId> CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const
46744673
{
46754674
LOCK2(m_nodes_mutex, cs_vPendingMasternodes);
46764675
auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash));
@@ -4679,7 +4678,7 @@ std::set<NodeId> CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType
46794678
}
46804679
const auto& proRegTxHashes = it->second;
46814680

4682-
std::set<NodeId> nodes;
4681+
std::unordered_set<NodeId> nodes;
46834682
for (const auto pnode : m_nodes) {
46844683
if (pnode->fDisconnect) {
46854684
continue;

src/net.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,12 +1501,12 @@ friend class CNode;
15011501
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex, !mutexMsgProc);
15021502

15031503
bool AddPendingMasternode(const uint256& proTxHash);
1504-
void SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes);
1505-
void SetMasternodeQuorumRelayMembers(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes);
1504+
void SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::unordered_set<uint256, StaticSaltedHasher>& proTxHashes);
1505+
void SetMasternodeQuorumRelayMembers(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::unordered_set<uint256, StaticSaltedHasher>& proTxHashes);
15061506
bool HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const;
1507-
std::set<uint256> GetMasternodeQuorums(Consensus::LLMQType llmqType) const;
1507+
std::unordered_set<uint256, StaticSaltedHasher> GetMasternodeQuorums(Consensus::LLMQType llmqType) const;
15081508
// also returns QWATCH nodes
1509-
std::set<NodeId> GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const;
1509+
std::unordered_set<NodeId> GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const;
15101510
void RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash);
15111511
bool IsMasternodeQuorumNode(const CNode* pnode, const CDeterministicMNList& tip_mn_list) const;
15121512
bool IsMasternodeQuorumRelayMember(const uint256& protxHash);
@@ -1815,8 +1815,8 @@ friend class CNode;
18151815

18161816
std::vector<uint256> vPendingMasternodes;
18171817
mutable RecursiveMutex cs_vPendingMasternodes;
1818-
std::map<std::pair<Consensus::LLMQType, uint256>, std::set<uint256>> masternodeQuorumNodes GUARDED_BY(cs_vPendingMasternodes);
1819-
std::map<std::pair<Consensus::LLMQType, uint256>, std::set<uint256>> masternodeQuorumRelayMembers GUARDED_BY(cs_vPendingMasternodes);
1818+
std::map<std::pair<Consensus::LLMQType, uint256>, std::unordered_set<uint256, StaticSaltedHasher>> masternodeQuorumNodes GUARDED_BY(cs_vPendingMasternodes);
1819+
std::map<std::pair<Consensus::LLMQType, uint256>, std::unordered_set<uint256, StaticSaltedHasher>> masternodeQuorumRelayMembers GUARDED_BY(cs_vPendingMasternodes);
18201820
std::set<uint256> masternodePendingProbes GUARDED_BY(cs_vPendingMasternodes);
18211821

18221822
mutable Mutex cs_mapSocketToNode;

0 commit comments

Comments
 (0)