15dda2efdSMircea Trofin #undef NDEBUG
25dda2efdSMircea Trofin #include <algorithm>
35dda2efdSMircea Trofin #include <cassert>
45dda2efdSMircea Trofin #include <cmath>
55dda2efdSMircea Trofin #include <cstdlib>
65dda2efdSMircea Trofin #include <vector>
7a290770fSMircea Trofin
85dda2efdSMircea Trofin #include "benchmark/benchmark.h"
95dda2efdSMircea Trofin #include "output_test.h"
105dda2efdSMircea Trofin
115dda2efdSMircea Trofin namespace {
125dda2efdSMircea Trofin
135dda2efdSMircea Trofin #define ADD_COMPLEXITY_CASES(...) \
145dda2efdSMircea Trofin int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__)
155dda2efdSMircea Trofin
AddComplexityTest(const std::string & test_name,const std::string & big_o_test_name,const std::string & rms_test_name,const std::string & big_o,int family_index)16a290770fSMircea Trofin int AddComplexityTest(const std::string &test_name,
17a290770fSMircea Trofin const std::string &big_o_test_name,
18a290770fSMircea Trofin const std::string &rms_test_name,
19a290770fSMircea Trofin const std::string &big_o, int family_index) {
205dda2efdSMircea Trofin SetSubstitutions({{"%name", test_name},
215dda2efdSMircea Trofin {"%bigo_name", big_o_test_name},
225dda2efdSMircea Trofin {"%rms_name", rms_test_name},
235dda2efdSMircea Trofin {"%bigo_str", "[ ]* %float " + big_o},
245dda2efdSMircea Trofin {"%bigo", big_o},
255dda2efdSMircea Trofin {"%rms", "[ ]*[0-9]+ %"}});
265dda2efdSMircea Trofin AddCases(
275dda2efdSMircea Trofin TC_ConsoleOut,
285dda2efdSMircea Trofin {{"^%bigo_name %bigo_str %bigo_str[ ]*$"},
29*a5b79717SMircea Trofin {"^%bigo_name", MR_Not}, // Assert we we didn't only matched a name.
305dda2efdSMircea Trofin {"^%rms_name %rms %rms[ ]*$", MR_Next}});
315dda2efdSMircea Trofin AddCases(
325dda2efdSMircea Trofin TC_JSONOut,
335dda2efdSMircea Trofin {{"\"name\": \"%bigo_name\",$"},
345dda2efdSMircea Trofin {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next},
355dda2efdSMircea Trofin {"\"per_family_instance_index\": 0,$", MR_Next},
365dda2efdSMircea Trofin {"\"run_name\": \"%name\",$", MR_Next},
375dda2efdSMircea Trofin {"\"run_type\": \"aggregate\",$", MR_Next},
385dda2efdSMircea Trofin {"\"repetitions\": %int,$", MR_Next},
395dda2efdSMircea Trofin {"\"threads\": 1,$", MR_Next},
405dda2efdSMircea Trofin {"\"aggregate_name\": \"BigO\",$", MR_Next},
41a290770fSMircea Trofin {"\"aggregate_unit\": \"time\",$", MR_Next},
425dda2efdSMircea Trofin {"\"cpu_coefficient\": %float,$", MR_Next},
435dda2efdSMircea Trofin {"\"real_coefficient\": %float,$", MR_Next},
445dda2efdSMircea Trofin {"\"big_o\": \"%bigo\",$", MR_Next},
455dda2efdSMircea Trofin {"\"time_unit\": \"ns\"$", MR_Next},
465dda2efdSMircea Trofin {"}", MR_Next},
475dda2efdSMircea Trofin {"\"name\": \"%rms_name\",$"},
485dda2efdSMircea Trofin {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next},
495dda2efdSMircea Trofin {"\"per_family_instance_index\": 0,$", MR_Next},
505dda2efdSMircea Trofin {"\"run_name\": \"%name\",$", MR_Next},
515dda2efdSMircea Trofin {"\"run_type\": \"aggregate\",$", MR_Next},
525dda2efdSMircea Trofin {"\"repetitions\": %int,$", MR_Next},
535dda2efdSMircea Trofin {"\"threads\": 1,$", MR_Next},
545dda2efdSMircea Trofin {"\"aggregate_name\": \"RMS\",$", MR_Next},
55a290770fSMircea Trofin {"\"aggregate_unit\": \"percentage\",$", MR_Next},
565dda2efdSMircea Trofin {"\"rms\": %float$", MR_Next},
575dda2efdSMircea Trofin {"}", MR_Next}});
585dda2efdSMircea Trofin AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"},
595dda2efdSMircea Trofin {"^\"%bigo_name\"", MR_Not},
605dda2efdSMircea Trofin {"^\"%rms_name\",,%float,%float,,,,,,$", MR_Next}});
615dda2efdSMircea Trofin return 0;
625dda2efdSMircea Trofin }
635dda2efdSMircea Trofin
645dda2efdSMircea Trofin } // end namespace
655dda2efdSMircea Trofin
665dda2efdSMircea Trofin // ========================================================================= //
675dda2efdSMircea Trofin // --------------------------- Testing BigO O(1) --------------------------- //
685dda2efdSMircea Trofin // ========================================================================= //
695dda2efdSMircea Trofin
BM_Complexity_O1(benchmark::State & state)705dda2efdSMircea Trofin void BM_Complexity_O1(benchmark::State &state) {
715dda2efdSMircea Trofin for (auto _ : state) {
72*a5b79717SMircea Trofin // This test requires a non-zero CPU time to avoid divide-by-zero
73*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
74*a5b79717SMircea Trofin long tmp = state.iterations();
75*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
76*a5b79717SMircea Trofin for (benchmark::IterationCount i = 0; i < state.iterations(); ++i) {
77*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
78*a5b79717SMircea Trofin tmp *= state.iterations();
79*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
805dda2efdSMircea Trofin }
81*a5b79717SMircea Trofin
82*a5b79717SMircea Trofin // always 1ns per iteration
83*a5b79717SMircea Trofin state.SetIterationTime(42 * 1e-9);
845dda2efdSMircea Trofin }
855dda2efdSMircea Trofin state.SetComplexityN(state.range(0));
865dda2efdSMircea Trofin }
875dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O1)
885dda2efdSMircea Trofin ->Range(1, 1 << 18)
89*a5b79717SMircea Trofin ->UseManualTime()
90*a5b79717SMircea Trofin ->Complexity(benchmark::o1);
91*a5b79717SMircea Trofin BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->UseManualTime()->Complexity();
92*a5b79717SMircea Trofin BENCHMARK(BM_Complexity_O1)
93*a5b79717SMircea Trofin ->Range(1, 1 << 18)
94*a5b79717SMircea Trofin ->UseManualTime()
__anon6994ed730202(benchmark::IterationCount) 955dda2efdSMircea Trofin ->Complexity([](benchmark::IterationCount) { return 1.0; });
965dda2efdSMircea Trofin
97*a5b79717SMircea Trofin const char *one_test_name = "BM_Complexity_O1/manual_time";
98*a5b79717SMircea Trofin const char *big_o_1_test_name = "BM_Complexity_O1/manual_time_BigO";
99*a5b79717SMircea Trofin const char *rms_o_1_test_name = "BM_Complexity_O1/manual_time_RMS";
100*a5b79717SMircea Trofin const char *enum_auto_big_o_1 = "\\([0-9]+\\)";
1015dda2efdSMircea Trofin const char *lambda_big_o_1 = "f\\(N\\)";
1025dda2efdSMircea Trofin
1035dda2efdSMircea Trofin // Add enum tests
1045dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
105*a5b79717SMircea Trofin enum_auto_big_o_1, /*family_index=*/0);
1065dda2efdSMircea Trofin
107*a5b79717SMircea Trofin // Add auto tests
1085dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
109*a5b79717SMircea Trofin enum_auto_big_o_1, /*family_index=*/1);
1105dda2efdSMircea Trofin
1115dda2efdSMircea Trofin // Add lambda tests
1125dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
1135dda2efdSMircea Trofin lambda_big_o_1, /*family_index=*/2);
1145dda2efdSMircea Trofin
1155dda2efdSMircea Trofin // ========================================================================= //
1165dda2efdSMircea Trofin // --------------------------- Testing BigO O(N) --------------------------- //
1175dda2efdSMircea Trofin // ========================================================================= //
1185dda2efdSMircea Trofin
BM_Complexity_O_N(benchmark::State & state)119*a5b79717SMircea Trofin void BM_Complexity_O_N(benchmark::State &state) {
120*a5b79717SMircea Trofin for (auto _ : state) {
121*a5b79717SMircea Trofin // This test requires a non-zero CPU time to avoid divide-by-zero
122*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
123*a5b79717SMircea Trofin long tmp = state.iterations();
124*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
125*a5b79717SMircea Trofin for (benchmark::IterationCount i = 0; i < state.iterations(); ++i) {
126*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
127*a5b79717SMircea Trofin tmp *= state.iterations();
128*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
1295dda2efdSMircea Trofin }
1305dda2efdSMircea Trofin
131*a5b79717SMircea Trofin // 1ns per iteration per entry
132*a5b79717SMircea Trofin state.SetIterationTime(static_cast<double>(state.range(0)) * 42.0 * 1e-9);
1335dda2efdSMircea Trofin }
1345dda2efdSMircea Trofin state.SetComplexityN(state.range(0));
1355dda2efdSMircea Trofin }
1365dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O_N)
1375dda2efdSMircea Trofin ->RangeMultiplier(2)
138*a5b79717SMircea Trofin ->Range(1 << 10, 1 << 20)
139*a5b79717SMircea Trofin ->UseManualTime()
1405dda2efdSMircea Trofin ->Complexity(benchmark::oN);
1415dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O_N)
1425dda2efdSMircea Trofin ->RangeMultiplier(2)
143*a5b79717SMircea Trofin ->Range(1 << 10, 1 << 20)
144*a5b79717SMircea Trofin ->UseManualTime()
145*a5b79717SMircea Trofin ->Complexity();
146*a5b79717SMircea Trofin BENCHMARK(BM_Complexity_O_N)
147*a5b79717SMircea Trofin ->RangeMultiplier(2)
148*a5b79717SMircea Trofin ->Range(1 << 10, 1 << 20)
149*a5b79717SMircea Trofin ->UseManualTime()
__anon6994ed730302(benchmark::IterationCount n) 1505dda2efdSMircea Trofin ->Complexity([](benchmark::IterationCount n) -> double {
1515dda2efdSMircea Trofin return static_cast<double>(n);
1525dda2efdSMircea Trofin });
1535dda2efdSMircea Trofin
154*a5b79717SMircea Trofin const char *n_test_name = "BM_Complexity_O_N/manual_time";
155*a5b79717SMircea Trofin const char *big_o_n_test_name = "BM_Complexity_O_N/manual_time_BigO";
156*a5b79717SMircea Trofin const char *rms_o_n_test_name = "BM_Complexity_O_N/manual_time_RMS";
1575dda2efdSMircea Trofin const char *enum_auto_big_o_n = "N";
1585dda2efdSMircea Trofin const char *lambda_big_o_n = "f\\(N\\)";
1595dda2efdSMircea Trofin
1605dda2efdSMircea Trofin // Add enum tests
1615dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
1625dda2efdSMircea Trofin enum_auto_big_o_n, /*family_index=*/3);
1635dda2efdSMircea Trofin
164*a5b79717SMircea Trofin // Add auto tests
165*a5b79717SMircea Trofin ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
166*a5b79717SMircea Trofin enum_auto_big_o_n, /*family_index=*/4);
167*a5b79717SMircea Trofin
1685dda2efdSMircea Trofin // Add lambda tests
1695dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
170*a5b79717SMircea Trofin lambda_big_o_n, /*family_index=*/5);
1715dda2efdSMircea Trofin
1725dda2efdSMircea Trofin // ========================================================================= //
173*a5b79717SMircea Trofin // ------------------------- Testing BigO O(NlgN) ------------------------- //
1745dda2efdSMircea Trofin // ========================================================================= //
1755dda2efdSMircea Trofin
176*a5b79717SMircea Trofin static const double kLog2E = 1.44269504088896340736;
BM_Complexity_O_N_log_N(benchmark::State & state)1775dda2efdSMircea Trofin static void BM_Complexity_O_N_log_N(benchmark::State &state) {
1785dda2efdSMircea Trofin for (auto _ : state) {
179*a5b79717SMircea Trofin // This test requires a non-zero CPU time to avoid divide-by-zero
180*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
181*a5b79717SMircea Trofin long tmp = state.iterations();
182*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
183*a5b79717SMircea Trofin for (benchmark::IterationCount i = 0; i < state.iterations(); ++i) {
184*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
185*a5b79717SMircea Trofin tmp *= state.iterations();
186*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
187*a5b79717SMircea Trofin }
188*a5b79717SMircea Trofin
189*a5b79717SMircea Trofin state.SetIterationTime(static_cast<double>(state.range(0)) * kLog2E *
190*a5b79717SMircea Trofin std::log(state.range(0)) * 42.0 * 1e-9);
1915dda2efdSMircea Trofin }
1925dda2efdSMircea Trofin state.SetComplexityN(state.range(0));
1935dda2efdSMircea Trofin }
1945dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O_N_log_N)
1955dda2efdSMircea Trofin ->RangeMultiplier(2)
196*a5b79717SMircea Trofin ->Range(1 << 10, 1U << 24)
197*a5b79717SMircea Trofin ->UseManualTime()
1985dda2efdSMircea Trofin ->Complexity(benchmark::oNLogN);
1995dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O_N_log_N)
2005dda2efdSMircea Trofin ->RangeMultiplier(2)
201*a5b79717SMircea Trofin ->Range(1 << 10, 1U << 24)
202*a5b79717SMircea Trofin ->UseManualTime()
203*a5b79717SMircea Trofin ->Complexity();
2045dda2efdSMircea Trofin BENCHMARK(BM_Complexity_O_N_log_N)
2055dda2efdSMircea Trofin ->RangeMultiplier(2)
206*a5b79717SMircea Trofin ->Range(1 << 10, 1U << 24)
207*a5b79717SMircea Trofin ->UseManualTime()
__anon6994ed730402(benchmark::IterationCount n) 208*a5b79717SMircea Trofin ->Complexity([](benchmark::IterationCount n) {
209*a5b79717SMircea Trofin return kLog2E * static_cast<double>(n) * std::log(static_cast<double>(n));
210*a5b79717SMircea Trofin });
2115dda2efdSMircea Trofin
212*a5b79717SMircea Trofin const char *n_lg_n_test_name = "BM_Complexity_O_N_log_N/manual_time";
213*a5b79717SMircea Trofin const char *big_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N/manual_time_BigO";
214*a5b79717SMircea Trofin const char *rms_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N/manual_time_RMS";
2155dda2efdSMircea Trofin const char *enum_auto_big_o_n_lg_n = "NlgN";
2165dda2efdSMircea Trofin const char *lambda_big_o_n_lg_n = "f\\(N\\)";
2175dda2efdSMircea Trofin
2185dda2efdSMircea Trofin // Add enum tests
2195dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
2205dda2efdSMircea Trofin rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n,
2215dda2efdSMircea Trofin /*family_index=*/6);
2225dda2efdSMircea Trofin
223*a5b79717SMircea Trofin // NOTE: auto big-o is wron.g
224*a5b79717SMircea Trofin ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
225*a5b79717SMircea Trofin rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n,
226*a5b79717SMircea Trofin /*family_index=*/7);
227*a5b79717SMircea Trofin
228*a5b79717SMircea Trofin //// Add lambda tests
2295dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
2305dda2efdSMircea Trofin rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n,
231*a5b79717SMircea Trofin /*family_index=*/8);
2325dda2efdSMircea Trofin
2335dda2efdSMircea Trofin // ========================================================================= //
2345dda2efdSMircea Trofin // -------- Testing formatting of Complexity with captured args ------------ //
2355dda2efdSMircea Trofin // ========================================================================= //
2365dda2efdSMircea Trofin
BM_ComplexityCaptureArgs(benchmark::State & state,int n)2375dda2efdSMircea Trofin void BM_ComplexityCaptureArgs(benchmark::State &state, int n) {
2385dda2efdSMircea Trofin for (auto _ : state) {
2395dda2efdSMircea Trofin // This test requires a non-zero CPU time to avoid divide-by-zero
2405dda2efdSMircea Trofin benchmark::DoNotOptimize(state.iterations());
241*a5b79717SMircea Trofin long tmp = state.iterations();
242*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
243*a5b79717SMircea Trofin for (benchmark::IterationCount i = 0; i < state.iterations(); ++i) {
244*a5b79717SMircea Trofin benchmark::DoNotOptimize(state.iterations());
245*a5b79717SMircea Trofin tmp *= state.iterations();
246*a5b79717SMircea Trofin benchmark::DoNotOptimize(tmp);
247*a5b79717SMircea Trofin }
248*a5b79717SMircea Trofin
249*a5b79717SMircea Trofin state.SetIterationTime(static_cast<double>(state.range(0)) * 42.0 * 1e-9);
2505dda2efdSMircea Trofin }
2515dda2efdSMircea Trofin state.SetComplexityN(n);
2525dda2efdSMircea Trofin }
2535dda2efdSMircea Trofin
2545dda2efdSMircea Trofin BENCHMARK_CAPTURE(BM_ComplexityCaptureArgs, capture_test, 100)
255*a5b79717SMircea Trofin ->UseManualTime()
2565dda2efdSMircea Trofin ->Complexity(benchmark::oN)
2575dda2efdSMircea Trofin ->Ranges({{1, 2}, {3, 4}});
2585dda2efdSMircea Trofin
2595dda2efdSMircea Trofin const std::string complexity_capture_name =
260*a5b79717SMircea Trofin "BM_ComplexityCaptureArgs/capture_test/manual_time";
2615dda2efdSMircea Trofin
2625dda2efdSMircea Trofin ADD_COMPLEXITY_CASES(complexity_capture_name, complexity_capture_name + "_BigO",
263*a5b79717SMircea Trofin complexity_capture_name + "_RMS", "N",
264*a5b79717SMircea Trofin /*family_index=*/9);
2655dda2efdSMircea Trofin
2665dda2efdSMircea Trofin // ========================================================================= //
2675dda2efdSMircea Trofin // --------------------------- TEST CASES END ------------------------------ //
2685dda2efdSMircea Trofin // ========================================================================= //
2695dda2efdSMircea Trofin
main(int argc,char * argv[])2705dda2efdSMircea Trofin int main(int argc, char *argv[]) { RunOutputTests(argc, argv); }
271