mempool_eviction.cpp raw

   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);
 148