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