1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
#include <atomic>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>
#include "benchmark/benchmark.h"
// Test that Setup() and Teardown() are called exactly once
// for each benchmark run (single-threaded).
namespace single {
static int setup_call = 0;
static int teardown_call = 0;
} // namespace single
static void DoSetup1(const benchmark::State& state) {
++single::setup_call;
// Setup/Teardown should never be called with any thread_idx != 0.
assert(state.thread_index() == 0);
}
static void DoTeardown1(const benchmark::State& state) {
++single::teardown_call;
assert(state.thread_index() == 0);
}
static void BM_with_setup(benchmark::State& state) {
for (auto s : state) {
}
}
BENCHMARK(BM_with_setup)
->Arg(1)
->Arg(3)
->Arg(5)
->Arg(7)
->Iterations(100)
->Setup(DoSetup1)
->Teardown(DoTeardown1);
// Test that Setup() and Teardown() are called once for each group of threads.
namespace concurrent {
static std::atomic<int> setup_call(0);
static std::atomic<int> teardown_call(0);
static std::atomic<int> func_call(0);
} // namespace concurrent
static void DoSetup2(const benchmark::State& state) {
concurrent::setup_call.fetch_add(1, std::memory_order_acquire);
assert(state.thread_index() == 0);
}
static void DoTeardown2(const benchmark::State& state) {
concurrent::teardown_call.fetch_add(1, std::memory_order_acquire);
assert(state.thread_index() == 0);
}
static void BM_concurrent(benchmark::State& state) {
for (auto s : state) {
}
concurrent::func_call.fetch_add(1, std::memory_order_acquire);
}
BENCHMARK(BM_concurrent)
->Setup(DoSetup2)
->Teardown(DoTeardown2)
->Iterations(100)
->Threads(5)
->Threads(10)
->Threads(15);
// Testing interaction with Fixture::Setup/Teardown
namespace fixture_interaction {
int setup = 0;
int fixture_setup = 0;
} // namespace fixture_interaction
#define FIXTURE_BECHMARK_NAME MyFixture
class FIXTURE_BECHMARK_NAME : public ::benchmark::Fixture {
public:
void SetUp(const ::benchmark::State&) BENCHMARK_OVERRIDE {
fixture_interaction::fixture_setup++;
}
~FIXTURE_BECHMARK_NAME() {}
};
BENCHMARK_F(FIXTURE_BECHMARK_NAME, BM_WithFixture)(benchmark::State& st) {
for (auto _ : st) {
}
}
static void DoSetupWithFixture(const benchmark::State&) {
fixture_interaction::setup++;
}
BENCHMARK_REGISTER_F(FIXTURE_BECHMARK_NAME, BM_WithFixture)
->Arg(1)
->Arg(3)
->Arg(5)
->Arg(7)
->Setup(DoSetupWithFixture)
->Repetitions(1)
->Iterations(100);
// Testing repetitions.
namespace repetitions {
int setup = 0;
}
static void DoSetupWithRepetitions(const benchmark::State&) {
repetitions::setup++;
}
static void BM_WithRep(benchmark::State& state) {
for (auto _ : state) {
}
}
BENCHMARK(BM_WithRep)
->Arg(1)
->Arg(3)
->Arg(5)
->Arg(7)
->Setup(DoSetupWithRepetitions)
->Iterations(100)
->Repetitions(4);
int main(int argc, char** argv) {
benchmark::Initialize(&argc, argv);
size_t ret = benchmark::RunSpecifiedBenchmarks(".");
assert(ret > 0);
// Setup/Teardown is called once for each arg group (1,3,5,7).
assert(single::setup_call == 4);
assert(single::teardown_call == 4);
// 3 group of threads calling this function (3,5,10).
assert(concurrent::setup_call.load(std::memory_order_relaxed) == 3);
assert(concurrent::teardown_call.load(std::memory_order_relaxed) == 3);
assert((5 + 10 + 15) ==
concurrent::func_call.load(std::memory_order_relaxed));
// Setup is called 4 times, once for each arg group (1,3,5,7)
assert(fixture_interaction::setup == 4);
// Fixture::Setup is called everytime the bm routine is run.
// The exact number is indeterministic, so we just assert that
// it's more than setup.
assert(fixture_interaction::fixture_setup > fixture_interaction::setup);
// Setup is call once for each repetition * num_arg = 4 * 4 = 16.
assert(repetitions::setup == 16);
return 0;
}
|