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