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