If you think unordered_map
is indeed faster (I’ll measure it once my benchmarking servers will be available), we could change the std::set
instances as well - and given that they’re array based, we might as well pre-allocate them.
0diff --git a/src/test/fuzz/package_eval.cpp b/src/test/fuzz/package_eval.cpp
1--- a/src/test/fuzz/package_eval.cpp (revision 147655098edde6feffbbe2c601d5874a7d3a3c5c)
2+++ b/src/test/fuzz/package_eval.cpp (date 1742211475064)
3@@ -57,9 +57,9 @@
4 }
5
6 struct OutpointsUpdater final : public CValidationInterface {
7- std::set<COutPoint>& m_mempool_outpoints;
8+ std::unordered_set<COutPoint, SaltedOutpointHasher>& m_mempool_outpoints;
9
10- explicit OutpointsUpdater(std::set<COutPoint>& r)
11+ explicit OutpointsUpdater(std::unordered_set<COutPoint, SaltedOutpointHasher>& r)
12 : m_mempool_outpoints{r} {}
13
14 void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t /* mempool_sequence */) override
15@@ -67,6 +67,7 @@
16 // for coins spent we always want to be able to rbf so they're not removed
17
18 // outputs from this tx can now be spent
19+ m_mempool_outpoints.reserve(m_mempool_outpoints.size() + tx.info.m_tx->vout.size());
20 for (uint32_t index{0}; index < tx.info.m_tx->vout.size(); ++index) {
21 m_mempool_outpoints.insert(COutPoint{tx.info.m_tx->GetHash(), index});
22 }
23@@ -75,6 +76,7 @@
24 void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t /* mempool_sequence */) override
25 {
26 // outpoints spent by this tx are now available
27+ m_mempool_outpoints.reserve(m_mempool_outpoints.size() + tx->vin.size());
28 for (const auto& input : tx->vin) {
29 // Could already exist if this was a replacement
30 m_mempool_outpoints.insert(input.prevout);
31@@ -200,8 +202,10 @@
32 MockTime(fuzzed_data_provider, chainstate);
33
34 // All RBF-spendable outpoints outside of the unsubmitted package
35- std::set<COutPoint> mempool_outpoints;
36+ std::unordered_set<COutPoint, SaltedOutpointHasher> mempool_outpoints;
37+ mempool_outpoints.reserve(g_outpoints_coinbase_init_mature.size());
38 std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
39+ outpoints_value.reserve(g_outpoints_coinbase_init_mature.size());
40 for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
41 Assert(mempool_outpoints.insert(outpoint).second);
42 outpoints_value[outpoint] = 50 * COIN;
43@@ -226,8 +230,10 @@
44
45 // Make small packages
46 const auto num_txs = outpoint_to_rbf ? 1 : fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 4);
47+ txs.reserve(num_txs);
48
49- std::set<COutPoint> package_outpoints;
50+ std::unordered_set<COutPoint, SaltedOutpointHasher> package_outpoints;
51+ package_outpoints.reserve((num_txs - 1) * 4);
52 while (txs.size() < num_txs) {
53 // Create transaction to add to the mempool
54 txs.emplace_back([&] {
55@@ -355,8 +361,10 @@
56 MockTime(fuzzed_data_provider, chainstate);
57
58 // All RBF-spendable outpoints outside of the unsubmitted package
59- std::set<COutPoint> mempool_outpoints;
60+ std::unordered_set<COutPoint, SaltedOutpointHasher> mempool_outpoints;
61+ mempool_outpoints.reserve(g_outpoints_coinbase_init_mature.size());
62 std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
63+ outpoints_value.reserve(g_outpoints_coinbase_init_mature.size());
64 for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
65 Assert(mempool_outpoints.insert(outpoint).second);
66 outpoints_value[outpoint] = 50 * COIN;
67@@ -378,7 +386,9 @@
68
69 // Make packages of 1-to-26 transactions
70 const auto num_txs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 26);
71- std::set<COutPoint> package_outpoints;
72+ txs.reserve(num_txs);
73+ std::unordered_set<COutPoint, SaltedOutpointHasher> package_outpoints;
74+ package_outpoints.reserve((num_txs - 1) * 4);
75 while (txs.size() < num_txs) {
76 // Create transaction to add to the mempool
77 txs.emplace_back([&] {