mempool_eviction.cpp
1 // Copyright (c) 2011-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <bench/bench.h> 6 #include <consensus/amount.h> 7 #include <kernel/cs_main.h> 8 #include <policy/policy.h> 9 #include <primitives/transaction.h> 10 #include <script/script.h> 11 #include <sync.h> 12 #include <test/util/setup_common.h> 13 #include <test/util/txmempool.h> 14 #include <txmempool.h> 15 #include <util/check.h> 16 17 #include <cstdint> 18 #include <memory> 19 #include <vector> 20 21 22 static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) 23 { 24 int64_t nTime = 0; 25 unsigned int nHeight = 1; 26 uint64_t sequence = 0; 27 bool spendsCoinbase = false; 28 unsigned int sigOpCost = 4; 29 LockPoints lp; 30 TryAddToMempool(pool, CTxMemPoolEntry( 31 tx, nFee, nTime, nHeight, sequence, 32 spendsCoinbase, sigOpCost, lp)); 33 } 34 35 // Right now this is only testing eviction performance in an extremely small 36 // mempool. Code needs to be written to generate a much wider variety of 37 // unique transactions for a more meaningful performance measurement. 38 static void MempoolEviction(benchmark::Bench& bench) 39 { 40 const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); 41 42 CMutableTransaction tx1 = CMutableTransaction(); 43 tx1.vin.resize(1); 44 tx1.vin[0].scriptSig = CScript() << OP_1; 45 tx1.vin[0].scriptWitness.stack.push_back({1}); 46 tx1.vout.resize(1); 47 tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; 48 tx1.vout[0].nValue = 10 * COIN; 49 50 CMutableTransaction tx2 = CMutableTransaction(); 51 tx2.vin.resize(1); 52 tx2.vin[0].scriptSig = CScript() << OP_2; 53 tx2.vin[0].scriptWitness.stack.push_back({2}); 54 tx2.vout.resize(1); 55 tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; 56 tx2.vout[0].nValue = 10 * COIN; 57 58 CMutableTransaction tx3 = CMutableTransaction(); 59 tx3.vin.resize(1); 60 tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0); 61 tx3.vin[0].scriptSig = CScript() << OP_2; 62 tx3.vin[0].scriptWitness.stack.push_back({3}); 63 tx3.vout.resize(1); 64 tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; 65 tx3.vout[0].nValue = 10 * COIN; 66 67 CMutableTransaction tx4 = CMutableTransaction(); 68 tx4.vin.resize(2); 69 tx4.vin[0].prevout.SetNull(); 70 tx4.vin[0].scriptSig = CScript() << OP_4; 71 tx4.vin[0].scriptWitness.stack.push_back({4}); 72 tx4.vin[1].prevout.SetNull(); 73 tx4.vin[1].scriptSig = CScript() << OP_4; 74 tx4.vin[1].scriptWitness.stack.push_back({4}); 75 tx4.vout.resize(2); 76 tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL; 77 tx4.vout[0].nValue = 10 * COIN; 78 tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL; 79 tx4.vout[1].nValue = 10 * COIN; 80 81 CMutableTransaction tx5 = CMutableTransaction(); 82 tx5.vin.resize(2); 83 tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0); 84 tx5.vin[0].scriptSig = CScript() << OP_4; 85 tx5.vin[0].scriptWitness.stack.push_back({4}); 86 tx5.vin[1].prevout.SetNull(); 87 tx5.vin[1].scriptSig = CScript() << OP_5; 88 tx5.vin[1].scriptWitness.stack.push_back({5}); 89 tx5.vout.resize(2); 90 tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL; 91 tx5.vout[0].nValue = 10 * COIN; 92 tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL; 93 tx5.vout[1].nValue = 10 * COIN; 94 95 CMutableTransaction tx6 = CMutableTransaction(); 96 tx6.vin.resize(2); 97 tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1); 98 tx6.vin[0].scriptSig = CScript() << OP_4; 99 tx6.vin[0].scriptWitness.stack.push_back({4}); 100 tx6.vin[1].prevout.SetNull(); 101 tx6.vin[1].scriptSig = CScript() << OP_6; 102 tx6.vin[1].scriptWitness.stack.push_back({6}); 103 tx6.vout.resize(2); 104 tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL; 105 tx6.vout[0].nValue = 10 * COIN; 106 tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL; 107 tx6.vout[1].nValue = 10 * COIN; 108 109 CMutableTransaction tx7 = CMutableTransaction(); 110 tx7.vin.resize(2); 111 tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0); 112 tx7.vin[0].scriptSig = CScript() << OP_5; 113 tx7.vin[0].scriptWitness.stack.push_back({5}); 114 tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0); 115 tx7.vin[1].scriptSig = CScript() << OP_6; 116 tx7.vin[1].scriptWitness.stack.push_back({6}); 117 tx7.vout.resize(2); 118 tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL; 119 tx7.vout[0].nValue = 10 * COIN; 120 tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; 121 tx7.vout[1].nValue = 10 * COIN; 122 123 CTxMemPool& pool = *Assert(testing_setup->m_node.mempool); 124 LOCK2(cs_main, pool.cs); 125 // Create transaction references outside the "hot loop" 126 const CTransactionRef tx1_r{MakeTransactionRef(tx1)}; 127 const CTransactionRef tx2_r{MakeTransactionRef(tx2)}; 128 const CTransactionRef tx3_r{MakeTransactionRef(tx3)}; 129 const CTransactionRef tx4_r{MakeTransactionRef(tx4)}; 130 const CTransactionRef tx5_r{MakeTransactionRef(tx5)}; 131 const CTransactionRef tx6_r{MakeTransactionRef(tx6)}; 132 const CTransactionRef tx7_r{MakeTransactionRef(tx7)}; 133 134 bench.run([&]() NO_THREAD_SAFETY_ANALYSIS { 135 AddTx(tx1_r, 10000LL, pool); 136 AddTx(tx2_r, 5000LL, pool); 137 AddTx(tx3_r, 20000LL, pool); 138 AddTx(tx4_r, 7000LL, pool); 139 AddTx(tx5_r, 1000LL, pool); 140 AddTx(tx6_r, 1100LL, pool); 141 AddTx(tx7_r, 9000LL, pool); 142 pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); 143 pool.TrimToSize(GetVirtualTransactionSize(*tx1_r)); 144 }); 145 } 146 147 BENCHMARK(MempoolEviction);