checkqueue.cpp raw

   1  // Copyright (c) 2015-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 <checkqueue.h>
   7  #include <common/system.h>
   8  #include <key.h>
   9  #include <prevector.h>
  10  #include <random.h>
  11  #include <script/script.h>
  12  
  13  #include <cstddef>
  14  #include <cstdint>
  15  #include <optional>
  16  #include <utility>
  17  #include <vector>
  18  
  19  static const size_t BATCHES = 101;
  20  static const size_t BATCH_SIZE = 30;
  21  static const unsigned int QUEUE_BATCH_SIZE = 128;
  22  
  23  // This Benchmark tests the CheckQueue with a slightly realistic workload,
  24  // where checks all contain a prevector that is indirect 50% of the time
  25  // and there is a little bit of work done between calls to Add.
  26  static void CCheckQueueSpeedPrevectorJob(benchmark::Bench& bench)
  27  {
  28      // We shouldn't ever be running with the checkqueue on a single core machine.
  29      if (GetNumCores() <= 1) return;
  30  
  31      ECC_Context ecc_context{};
  32  
  33      struct PrevectorJob {
  34          prevector<CScriptBase::STATIC_SIZE, uint8_t> p;
  35          explicit PrevectorJob(FastRandomContext& insecure_rand){
  36              p.resize(insecure_rand.randrange(CScriptBase::STATIC_SIZE * 2));
  37          }
  38          std::optional<int> operator()()
  39          {
  40              return std::nullopt;
  41          }
  42      };
  43  
  44      // The main thread should be counted to prevent thread oversubscription, and
  45      // to decrease the variance of benchmark results.
  46      int worker_threads_num{GetNumCores() - 1};
  47      CCheckQueue<PrevectorJob> queue{QUEUE_BATCH_SIZE, worker_threads_num};
  48  
  49      // create all the data once, then submit copies in the benchmark.
  50      FastRandomContext insecure_rand(true);
  51      std::vector<std::vector<PrevectorJob>> vBatches(BATCHES);
  52      for (auto& vChecks : vBatches) {
  53          vChecks.reserve(BATCH_SIZE);
  54          for (size_t x = 0; x < BATCH_SIZE; ++x)
  55              vChecks.emplace_back(insecure_rand);
  56      }
  57  
  58      bench.minEpochIterations(10).batch(BATCH_SIZE * BATCHES).unit("job").run([&] {
  59          // Make insecure_rand here so that each iteration is identical.
  60          CCheckQueueControl<PrevectorJob> control(queue);
  61          for (auto vChecks : vBatches) {
  62              control.Add(std::move(vChecks));
  63          }
  64          // control waits for completion by RAII, but
  65          // it is done explicitly here for clarity
  66          control.Complete();
  67      });
  68  }
  69  BENCHMARK(CCheckQueueSpeedPrevectorJob);
  70