1 // Copyright (c) 2015 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.
5 #include <bench/bench.h>
7 #include <validation.h>
8 #include <checkqueue.h>
11 #include <boost/thread/thread.hpp>
15 // This Benchmark tests the CheckQueue with the lightest
16 // weight Checks, so it should make any lock contention
17 // particularly visible
18 static const int MIN_CORES
= 2;
19 static const size_t BATCHES
= 101;
20 static const size_t BATCH_SIZE
= 30;
21 static const int PREVECTOR_SIZE
= 28;
22 static const unsigned int QUEUE_BATCH_SIZE
= 128;
23 static void CCheckQueueSpeed(benchmark::State
& state
)
25 struct FakeJobNoWork
{
30 void swap(FakeJobNoWork
& x
){};
32 CCheckQueue
<FakeJobNoWork
> queue
{QUEUE_BATCH_SIZE
};
33 boost::thread_group tg
;
34 for (auto x
= 0; x
< std::max(MIN_CORES
, GetNumCores()); ++x
) {
35 tg
.create_thread([&]{queue
.Thread();});
37 while (state
.KeepRunning()) {
38 CCheckQueueControl
<FakeJobNoWork
> control(&queue
);
40 // We call Add a number of times to simulate the behavior of adding
41 // a block of transactions at once.
43 std::vector
<std::vector
<FakeJobNoWork
>> vBatches(BATCHES
);
44 for (auto& vChecks
: vBatches
) {
45 vChecks
.resize(BATCH_SIZE
);
47 for (auto& vChecks
: vBatches
) {
48 // We can't make vChecks in the inner loop because we want to measure
49 // the cost of getting the memory to each thread and we might get the same
53 // control waits for completion by RAII, but
54 // it is done explicitly here for clarity
61 // This Benchmark tests the CheckQueue with a slightly realistic workload,
62 // where checks all contain a prevector that is indirect 50% of the time
63 // and there is a little bit of work done between calls to Add.
64 static void CCheckQueueSpeedPrevectorJob(benchmark::State
& state
)
67 prevector
<PREVECTOR_SIZE
, uint8_t> p
;
70 explicit PrevectorJob(FastRandomContext
& insecure_rand
){
71 p
.resize(insecure_rand
.randrange(PREVECTOR_SIZE
*2));
77 void swap(PrevectorJob
& x
){p
.swap(x
.p
);};
79 CCheckQueue
<PrevectorJob
> queue
{QUEUE_BATCH_SIZE
};
80 boost::thread_group tg
;
81 for (auto x
= 0; x
< std::max(MIN_CORES
, GetNumCores()); ++x
) {
82 tg
.create_thread([&]{queue
.Thread();});
84 while (state
.KeepRunning()) {
85 // Make insecure_rand here so that each iteration is identical.
86 FastRandomContext
insecure_rand(true);
87 CCheckQueueControl
<PrevectorJob
> control(&queue
);
88 std::vector
<std::vector
<PrevectorJob
>> vBatches(BATCHES
);
89 for (auto& vChecks
: vBatches
) {
90 vChecks
.reserve(BATCH_SIZE
);
91 for (size_t x
= 0; x
< BATCH_SIZE
; ++x
)
92 vChecks
.emplace_back(insecure_rand
);
95 // control waits for completion by RAII, but
96 // it is done explicitly here for clarity
102 BENCHMARK(CCheckQueueSpeed
);
103 BENCHMARK(CCheckQueueSpeedPrevectorJob
);