/ src / bench / mempool_eviction.cpp
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);