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