1a8c51b3fSopenharmony_ci#undef NDEBUG 2a8c51b3fSopenharmony_ci#include <algorithm> 3a8c51b3fSopenharmony_ci#include <cassert> 4a8c51b3fSopenharmony_ci#include <cmath> 5a8c51b3fSopenharmony_ci#include <cstdlib> 6a8c51b3fSopenharmony_ci#include <vector> 7a8c51b3fSopenharmony_ci 8a8c51b3fSopenharmony_ci#include "benchmark/benchmark.h" 9a8c51b3fSopenharmony_ci#include "output_test.h" 10a8c51b3fSopenharmony_ci 11a8c51b3fSopenharmony_cinamespace { 12a8c51b3fSopenharmony_ci 13a8c51b3fSopenharmony_ci#define ADD_COMPLEXITY_CASES(...) \ 14a8c51b3fSopenharmony_ci int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__) 15a8c51b3fSopenharmony_ci 16a8c51b3fSopenharmony_ciint AddComplexityTest(const std::string &test_name, 17a8c51b3fSopenharmony_ci const std::string &big_o_test_name, 18a8c51b3fSopenharmony_ci const std::string &rms_test_name, 19a8c51b3fSopenharmony_ci const std::string &big_o, int family_index) { 20a8c51b3fSopenharmony_ci SetSubstitutions({{"%name", test_name}, 21a8c51b3fSopenharmony_ci {"%bigo_name", big_o_test_name}, 22a8c51b3fSopenharmony_ci {"%rms_name", rms_test_name}, 23a8c51b3fSopenharmony_ci {"%bigo_str", "[ ]* %float " + big_o}, 24a8c51b3fSopenharmony_ci {"%bigo", big_o}, 25a8c51b3fSopenharmony_ci {"%rms", "[ ]*[0-9]+ %"}}); 26a8c51b3fSopenharmony_ci AddCases( 27a8c51b3fSopenharmony_ci TC_ConsoleOut, 28a8c51b3fSopenharmony_ci {{"^%bigo_name %bigo_str %bigo_str[ ]*$"}, 29a8c51b3fSopenharmony_ci {"^%bigo_name", MR_Not}, // Assert we we didn't only matched a name. 30a8c51b3fSopenharmony_ci {"^%rms_name %rms %rms[ ]*$", MR_Next}}); 31a8c51b3fSopenharmony_ci AddCases( 32a8c51b3fSopenharmony_ci TC_JSONOut, 33a8c51b3fSopenharmony_ci {{"\"name\": \"%bigo_name\",$"}, 34a8c51b3fSopenharmony_ci {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next}, 35a8c51b3fSopenharmony_ci {"\"per_family_instance_index\": 0,$", MR_Next}, 36a8c51b3fSopenharmony_ci {"\"run_name\": \"%name\",$", MR_Next}, 37a8c51b3fSopenharmony_ci {"\"run_type\": \"aggregate\",$", MR_Next}, 38a8c51b3fSopenharmony_ci {"\"repetitions\": %int,$", MR_Next}, 39a8c51b3fSopenharmony_ci {"\"threads\": 1,$", MR_Next}, 40a8c51b3fSopenharmony_ci {"\"aggregate_name\": \"BigO\",$", MR_Next}, 41a8c51b3fSopenharmony_ci {"\"aggregate_unit\": \"time\",$", MR_Next}, 42a8c51b3fSopenharmony_ci {"\"cpu_coefficient\": %float,$", MR_Next}, 43a8c51b3fSopenharmony_ci {"\"real_coefficient\": %float,$", MR_Next}, 44a8c51b3fSopenharmony_ci {"\"big_o\": \"%bigo\",$", MR_Next}, 45a8c51b3fSopenharmony_ci {"\"time_unit\": \"ns\"$", MR_Next}, 46a8c51b3fSopenharmony_ci {"}", MR_Next}, 47a8c51b3fSopenharmony_ci {"\"name\": \"%rms_name\",$"}, 48a8c51b3fSopenharmony_ci {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next}, 49a8c51b3fSopenharmony_ci {"\"per_family_instance_index\": 0,$", MR_Next}, 50a8c51b3fSopenharmony_ci {"\"run_name\": \"%name\",$", MR_Next}, 51a8c51b3fSopenharmony_ci {"\"run_type\": \"aggregate\",$", MR_Next}, 52a8c51b3fSopenharmony_ci {"\"repetitions\": %int,$", MR_Next}, 53a8c51b3fSopenharmony_ci {"\"threads\": 1,$", MR_Next}, 54a8c51b3fSopenharmony_ci {"\"aggregate_name\": \"RMS\",$", MR_Next}, 55a8c51b3fSopenharmony_ci {"\"aggregate_unit\": \"percentage\",$", MR_Next}, 56a8c51b3fSopenharmony_ci {"\"rms\": %float$", MR_Next}, 57a8c51b3fSopenharmony_ci {"}", MR_Next}}); 58a8c51b3fSopenharmony_ci AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"}, 59a8c51b3fSopenharmony_ci {"^\"%bigo_name\"", MR_Not}, 60a8c51b3fSopenharmony_ci {"^\"%rms_name\",,%float,%float,,,,,,$", MR_Next}}); 61a8c51b3fSopenharmony_ci return 0; 62a8c51b3fSopenharmony_ci} 63a8c51b3fSopenharmony_ci 64a8c51b3fSopenharmony_ci} // end namespace 65a8c51b3fSopenharmony_ci 66a8c51b3fSopenharmony_ci// ========================================================================= // 67a8c51b3fSopenharmony_ci// --------------------------- Testing BigO O(1) --------------------------- // 68a8c51b3fSopenharmony_ci// ========================================================================= // 69a8c51b3fSopenharmony_ci 70a8c51b3fSopenharmony_civoid BM_Complexity_O1(benchmark::State &state) { 71a8c51b3fSopenharmony_ci for (auto _ : state) { 72a8c51b3fSopenharmony_ci for (int i = 0; i < 1024; ++i) { 73a8c51b3fSopenharmony_ci benchmark::DoNotOptimize(i); 74a8c51b3fSopenharmony_ci } 75a8c51b3fSopenharmony_ci } 76a8c51b3fSopenharmony_ci state.SetComplexityN(state.range(0)); 77a8c51b3fSopenharmony_ci} 78a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1); 79a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(); 80a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1) 81a8c51b3fSopenharmony_ci ->Range(1, 1 << 18) 82a8c51b3fSopenharmony_ci ->Complexity([](benchmark::IterationCount) { return 1.0; }); 83a8c51b3fSopenharmony_ci 84a8c51b3fSopenharmony_ciconst char *one_test_name = "BM_Complexity_O1"; 85a8c51b3fSopenharmony_ciconst char *big_o_1_test_name = "BM_Complexity_O1_BigO"; 86a8c51b3fSopenharmony_ciconst char *rms_o_1_test_name = "BM_Complexity_O1_RMS"; 87a8c51b3fSopenharmony_ciconst char *enum_big_o_1 = "\\([0-9]+\\)"; 88a8c51b3fSopenharmony_ci// FIXME: Tolerate both '(1)' and 'lgN' as output when the complexity is auto 89a8c51b3fSopenharmony_ci// deduced. 90a8c51b3fSopenharmony_ci// See https://github.com/google/benchmark/issues/272 91a8c51b3fSopenharmony_ciconst char *auto_big_o_1 = "(\\([0-9]+\\))|(lgN)"; 92a8c51b3fSopenharmony_ciconst char *lambda_big_o_1 = "f\\(N\\)"; 93a8c51b3fSopenharmony_ci 94a8c51b3fSopenharmony_ci// Add enum tests 95a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, 96a8c51b3fSopenharmony_ci enum_big_o_1, /*family_index=*/0); 97a8c51b3fSopenharmony_ci 98a8c51b3fSopenharmony_ci// Add auto enum tests 99a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, 100a8c51b3fSopenharmony_ci auto_big_o_1, /*family_index=*/1); 101a8c51b3fSopenharmony_ci 102a8c51b3fSopenharmony_ci// Add lambda tests 103a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, 104a8c51b3fSopenharmony_ci lambda_big_o_1, /*family_index=*/2); 105a8c51b3fSopenharmony_ci 106a8c51b3fSopenharmony_ci// ========================================================================= // 107a8c51b3fSopenharmony_ci// --------------------------- Testing BigO O(N) --------------------------- // 108a8c51b3fSopenharmony_ci// ========================================================================= // 109a8c51b3fSopenharmony_ci 110a8c51b3fSopenharmony_cistd::vector<int> ConstructRandomVector(int64_t size) { 111a8c51b3fSopenharmony_ci std::vector<int> v; 112a8c51b3fSopenharmony_ci v.reserve(static_cast<size_t>(size)); 113a8c51b3fSopenharmony_ci for (int i = 0; i < size; ++i) { 114a8c51b3fSopenharmony_ci v.push_back(static_cast<int>(std::rand() % size)); 115a8c51b3fSopenharmony_ci } 116a8c51b3fSopenharmony_ci return v; 117a8c51b3fSopenharmony_ci} 118a8c51b3fSopenharmony_ci 119a8c51b3fSopenharmony_civoid BM_Complexity_O_N(benchmark::State &state) { 120a8c51b3fSopenharmony_ci auto v = ConstructRandomVector(state.range(0)); 121a8c51b3fSopenharmony_ci // Test worst case scenario (item not in vector) 122a8c51b3fSopenharmony_ci const int64_t item_not_in_vector = state.range(0) * 2; 123a8c51b3fSopenharmony_ci for (auto _ : state) { 124a8c51b3fSopenharmony_ci auto it = std::find(v.begin(), v.end(), item_not_in_vector); 125a8c51b3fSopenharmony_ci benchmark::DoNotOptimize(it); 126a8c51b3fSopenharmony_ci } 127a8c51b3fSopenharmony_ci state.SetComplexityN(state.range(0)); 128a8c51b3fSopenharmony_ci} 129a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N) 130a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 131a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 132a8c51b3fSopenharmony_ci ->Complexity(benchmark::oN); 133a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N) 134a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 135a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 136a8c51b3fSopenharmony_ci ->Complexity([](benchmark::IterationCount n) -> double { 137a8c51b3fSopenharmony_ci return static_cast<double>(n); 138a8c51b3fSopenharmony_ci }); 139a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N) 140a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 141a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 142a8c51b3fSopenharmony_ci ->Complexity(); 143a8c51b3fSopenharmony_ci 144a8c51b3fSopenharmony_ciconst char *n_test_name = "BM_Complexity_O_N"; 145a8c51b3fSopenharmony_ciconst char *big_o_n_test_name = "BM_Complexity_O_N_BigO"; 146a8c51b3fSopenharmony_ciconst char *rms_o_n_test_name = "BM_Complexity_O_N_RMS"; 147a8c51b3fSopenharmony_ciconst char *enum_auto_big_o_n = "N"; 148a8c51b3fSopenharmony_ciconst char *lambda_big_o_n = "f\\(N\\)"; 149a8c51b3fSopenharmony_ci 150a8c51b3fSopenharmony_ci// Add enum tests 151a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, 152a8c51b3fSopenharmony_ci enum_auto_big_o_n, /*family_index=*/3); 153a8c51b3fSopenharmony_ci 154a8c51b3fSopenharmony_ci// Add lambda tests 155a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, 156a8c51b3fSopenharmony_ci lambda_big_o_n, /*family_index=*/4); 157a8c51b3fSopenharmony_ci 158a8c51b3fSopenharmony_ci// ========================================================================= // 159a8c51b3fSopenharmony_ci// ------------------------- Testing BigO O(N*lgN) ------------------------- // 160a8c51b3fSopenharmony_ci// ========================================================================= // 161a8c51b3fSopenharmony_ci 162a8c51b3fSopenharmony_cistatic void BM_Complexity_O_N_log_N(benchmark::State &state) { 163a8c51b3fSopenharmony_ci auto v = ConstructRandomVector(state.range(0)); 164a8c51b3fSopenharmony_ci for (auto _ : state) { 165a8c51b3fSopenharmony_ci std::sort(v.begin(), v.end()); 166a8c51b3fSopenharmony_ci } 167a8c51b3fSopenharmony_ci state.SetComplexityN(state.range(0)); 168a8c51b3fSopenharmony_ci} 169a8c51b3fSopenharmony_cistatic const double kLog2E = 1.44269504088896340736; 170a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N) 171a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 172a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 173a8c51b3fSopenharmony_ci ->Complexity(benchmark::oNLogN); 174a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N) 175a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 176a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 177a8c51b3fSopenharmony_ci ->Complexity([](benchmark::IterationCount n) { 178a8c51b3fSopenharmony_ci return kLog2E * static_cast<double>(n) * log(static_cast<double>(n)); 179a8c51b3fSopenharmony_ci }); 180a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N) 181a8c51b3fSopenharmony_ci ->RangeMultiplier(2) 182a8c51b3fSopenharmony_ci ->Range(1 << 10, 1 << 16) 183a8c51b3fSopenharmony_ci ->Complexity(); 184a8c51b3fSopenharmony_ci 185a8c51b3fSopenharmony_ciconst char *n_lg_n_test_name = "BM_Complexity_O_N_log_N"; 186a8c51b3fSopenharmony_ciconst char *big_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_BigO"; 187a8c51b3fSopenharmony_ciconst char *rms_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_RMS"; 188a8c51b3fSopenharmony_ciconst char *enum_auto_big_o_n_lg_n = "NlgN"; 189a8c51b3fSopenharmony_ciconst char *lambda_big_o_n_lg_n = "f\\(N\\)"; 190a8c51b3fSopenharmony_ci 191a8c51b3fSopenharmony_ci// Add enum tests 192a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, 193a8c51b3fSopenharmony_ci rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n, 194a8c51b3fSopenharmony_ci /*family_index=*/6); 195a8c51b3fSopenharmony_ci 196a8c51b3fSopenharmony_ci// Add lambda tests 197a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, 198a8c51b3fSopenharmony_ci rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n, 199a8c51b3fSopenharmony_ci /*family_index=*/7); 200a8c51b3fSopenharmony_ci 201a8c51b3fSopenharmony_ci// ========================================================================= // 202a8c51b3fSopenharmony_ci// -------- Testing formatting of Complexity with captured args ------------ // 203a8c51b3fSopenharmony_ci// ========================================================================= // 204a8c51b3fSopenharmony_ci 205a8c51b3fSopenharmony_civoid BM_ComplexityCaptureArgs(benchmark::State &state, int n) { 206a8c51b3fSopenharmony_ci for (auto _ : state) { 207a8c51b3fSopenharmony_ci // This test requires a non-zero CPU time to avoid divide-by-zero 208a8c51b3fSopenharmony_ci auto iterations = state.iterations(); 209a8c51b3fSopenharmony_ci benchmark::DoNotOptimize(iterations); 210a8c51b3fSopenharmony_ci } 211a8c51b3fSopenharmony_ci state.SetComplexityN(n); 212a8c51b3fSopenharmony_ci} 213a8c51b3fSopenharmony_ci 214a8c51b3fSopenharmony_ciBENCHMARK_CAPTURE(BM_ComplexityCaptureArgs, capture_test, 100) 215a8c51b3fSopenharmony_ci ->Complexity(benchmark::oN) 216a8c51b3fSopenharmony_ci ->Ranges({{1, 2}, {3, 4}}); 217a8c51b3fSopenharmony_ci 218a8c51b3fSopenharmony_ciconst std::string complexity_capture_name = 219a8c51b3fSopenharmony_ci "BM_ComplexityCaptureArgs/capture_test"; 220a8c51b3fSopenharmony_ci 221a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(complexity_capture_name, complexity_capture_name + "_BigO", 222a8c51b3fSopenharmony_ci complexity_capture_name + "_RMS", "N", /*family_index=*/9); 223a8c51b3fSopenharmony_ci 224a8c51b3fSopenharmony_ci// ========================================================================= // 225a8c51b3fSopenharmony_ci// --------------------------- TEST CASES END ------------------------------ // 226a8c51b3fSopenharmony_ci// ========================================================================= // 227a8c51b3fSopenharmony_ci 228a8c51b3fSopenharmony_ciint main(int argc, char *argv[]) { RunOutputTests(argc, argv); } 229