mempool_eviction.cpp raw

   1  // Copyright (c) 2011-2022 The Limenka 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      double dPriority = 10.0;
  26      unsigned int nHeight = 1;
  27      uint64_t sequence = 0;
  28      bool spendsCoinbase = false;
  29      unsigned int sigOpCost = 4;
  30      LockPoints lp;
  31      AddToMempool(pool, CTxMemPoolEntry(
  32          tx, nFee, nTime, nHeight, sequence,
  33          {
  34              .inputs_coin_age = static_cast<uint64_t>(dPriority * tx->GetValueOut()),
  35              .in_chain_input_value = tx->GetValueOut(),
  36          },
  37          spendsCoinbase, /*extra_weight=*/0, sigOpCost, lp));
  38  }
  39  
  40  // Right now this is only testing eviction performance in an extremely small
  41  // mempool. Code needs to be written to generate a much wider variety of
  42  // unique transactions for a more meaningful performance measurement.
  43  static void MempoolEviction(benchmark::Bench& bench)
  44  {
  45      const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
  46  
  47      CMutableTransaction tx1 = CMutableTransaction();
  48      tx1.vin.resize(1);
  49      tx1.vin[0].scriptSig = CScript() << OP_1;
  50      tx1.vin[0].scriptWitness.stack.push_back({1});
  51      tx1.vout.resize(1);
  52      tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
  53      tx1.vout[0].nValue = 10 * COIN;
  54  
  55      CMutableTransaction tx2 = CMutableTransaction();
  56      tx2.vin.resize(1);
  57      tx2.vin[0].scriptSig = CScript() << OP_2;
  58      tx2.vin[0].scriptWitness.stack.push_back({2});
  59      tx2.vout.resize(1);
  60      tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
  61      tx2.vout[0].nValue = 10 * COIN;
  62  
  63      CMutableTransaction tx3 = CMutableTransaction();
  64      tx3.vin.resize(1);
  65      tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
  66      tx3.vin[0].scriptSig = CScript() << OP_2;
  67      tx3.vin[0].scriptWitness.stack.push_back({3});
  68      tx3.vout.resize(1);
  69      tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
  70      tx3.vout[0].nValue = 10 * COIN;
  71  
  72      CMutableTransaction tx4 = CMutableTransaction();
  73      tx4.vin.resize(2);
  74      tx4.vin[0].prevout.SetNull();
  75      tx4.vin[0].scriptSig = CScript() << OP_4;
  76      tx4.vin[0].scriptWitness.stack.push_back({4});
  77      tx4.vin[1].prevout.SetNull();
  78      tx4.vin[1].scriptSig = CScript() << OP_4;
  79      tx4.vin[1].scriptWitness.stack.push_back({4});
  80      tx4.vout.resize(2);
  81      tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
  82      tx4.vout[0].nValue = 10 * COIN;
  83      tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
  84      tx4.vout[1].nValue = 10 * COIN;
  85  
  86      CMutableTransaction tx5 = CMutableTransaction();
  87      tx5.vin.resize(2);
  88      tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
  89      tx5.vin[0].scriptSig = CScript() << OP_4;
  90      tx5.vin[0].scriptWitness.stack.push_back({4});
  91      tx5.vin[1].prevout.SetNull();
  92      tx5.vin[1].scriptSig = CScript() << OP_5;
  93      tx5.vin[1].scriptWitness.stack.push_back({5});
  94      tx5.vout.resize(2);
  95      tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
  96      tx5.vout[0].nValue = 10 * COIN;
  97      tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
  98      tx5.vout[1].nValue = 10 * COIN;
  99  
 100      CMutableTransaction tx6 = CMutableTransaction();
 101      tx6.vin.resize(2);
 102      tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
 103      tx6.vin[0].scriptSig = CScript() << OP_4;
 104      tx6.vin[0].scriptWitness.stack.push_back({4});
 105      tx6.vin[1].prevout.SetNull();
 106      tx6.vin[1].scriptSig = CScript() << OP_6;
 107      tx6.vin[1].scriptWitness.stack.push_back({6});
 108      tx6.vout.resize(2);
 109      tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
 110      tx6.vout[0].nValue = 10 * COIN;
 111      tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
 112      tx6.vout[1].nValue = 10 * COIN;
 113  
 114      CMutableTransaction tx7 = CMutableTransaction();
 115      tx7.vin.resize(2);
 116      tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
 117      tx7.vin[0].scriptSig = CScript() << OP_5;
 118      tx7.vin[0].scriptWitness.stack.push_back({5});
 119      tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
 120      tx7.vin[1].scriptSig = CScript() << OP_6;
 121      tx7.vin[1].scriptWitness.stack.push_back({6});
 122      tx7.vout.resize(2);
 123      tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
 124      tx7.vout[0].nValue = 10 * COIN;
 125      tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
 126      tx7.vout[1].nValue = 10 * COIN;
 127  
 128      CTxMemPool& pool = *Assert(testing_setup->m_node.mempool);
 129      LOCK2(cs_main, pool.cs);
 130      // Create transaction references outside the "hot loop"
 131      const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
 132      const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
 133      const CTransactionRef tx3_r{MakeTransactionRef(tx3)};
 134      const CTransactionRef tx4_r{MakeTransactionRef(tx4)};
 135      const CTransactionRef tx5_r{MakeTransactionRef(tx5)};
 136      const CTransactionRef tx6_r{MakeTransactionRef(tx6)};
 137      const CTransactionRef tx7_r{MakeTransactionRef(tx7)};
 138  
 139      bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
 140          AddTx(tx1_r, 10000LL, pool);
 141          AddTx(tx2_r, 5000LL, pool);
 142          AddTx(tx3_r, 20000LL, pool);
 143          AddTx(tx4_r, 7000LL, pool);
 144          AddTx(tx5_r, 1000LL, pool);
 145          AddTx(tx6_r, 1100LL, pool);
 146          AddTx(tx7_r, 9000LL, pool);
 147          pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
 148          pool.TrimToSize(GetVirtualTransactionSize(*tx1_r));
 149      });
 150  }
 151  
 152  BENCHMARK(MempoolEviction, benchmark::PriorityLevel::HIGH);
 153