1 #include "benchmark/benchmark.h"
2 #include "GenerateInput.hpp"
3 #include "test_iterators.h"
4 #include "filesystem_include.hpp"
5 
6 static const size_t TestNumInputs = 1024;
7 
8 
9 template <class GenInputs>
BM_PathConstructString(benchmark::State & st,GenInputs gen)10 void BM_PathConstructString(benchmark::State &st, GenInputs gen) {
11   using fs::path;
12   const auto in = gen(st.range(0));
13   path PP;
14   for (auto& Part : in)
15     PP /= Part;
16   benchmark::DoNotOptimize(PP.native().data());
17   while (st.KeepRunning()) {
18     const path P(PP.native());
19     benchmark::DoNotOptimize(P.native().data());
20   }
21   st.SetComplexityN(st.range(0));
22 }
23 BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
24   getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
25 
26 
27 template <class GenInputs>
BM_PathConstructCStr(benchmark::State & st,GenInputs gen)28 void BM_PathConstructCStr(benchmark::State &st, GenInputs gen) {
29   using fs::path;
30   const auto in = gen(st.range(0));
31   path PP;
32   for (auto& Part : in)
33     PP /= Part;
34   benchmark::DoNotOptimize(PP.native().data());
35   while (st.KeepRunning()) {
36     const path P(PP.native().c_str());
37     benchmark::DoNotOptimize(P.native().data());
38   }
39 }
40 BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
41   getRandomStringInputs)->Arg(TestNumInputs);
42 
43 
44 template <template <class...> class ItType, class GenInputs>
BM_PathConstructIter(benchmark::State & st,GenInputs gen)45 void BM_PathConstructIter(benchmark::State &st, GenInputs gen) {
46   using fs::path;
47   using Iter = ItType<std::string::const_iterator>;
48   const auto in = gen(st.range(0));
49   path PP;
50   for (auto& Part : in)
51     PP /= Part;
52   auto Start = Iter(PP.native().begin());
53   auto End = Iter(PP.native().end());
54   benchmark::DoNotOptimize(PP.native().data());
55   benchmark::DoNotOptimize(Start);
56   benchmark::DoNotOptimize(End);
57   while (st.KeepRunning()) {
58     const path P(Start, End);
59     benchmark::DoNotOptimize(P.native().data());
60   }
61   st.SetComplexityN(st.range(0));
62 }
63 template <class GenInputs>
BM_PathConstructInputIter(benchmark::State & st,GenInputs gen)64 void BM_PathConstructInputIter(benchmark::State &st, GenInputs gen) {
65   BM_PathConstructIter<input_iterator>(st, gen);
66 }
67 template <class GenInputs>
BM_PathConstructForwardIter(benchmark::State & st,GenInputs gen)68 void BM_PathConstructForwardIter(benchmark::State &st, GenInputs gen) {
69   BM_PathConstructIter<forward_iterator>(st, gen);
70 }
71 BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string,
72   getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
73 BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string,
74   getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
75 
76 
77 template <class GenInputs>
BM_PathIterateMultipleTimes(benchmark::State & st,GenInputs gen)78 void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
79   using fs::path;
80   const auto in = gen(st.range(0));
81   path PP;
82   for (auto& Part : in)
83     PP /= Part;
84   benchmark::DoNotOptimize(PP.native().data());
85   while (st.KeepRunning()) {
86     for (auto &E : PP) {
87       benchmark::DoNotOptimize(E.native().data());
88     }
89     benchmark::ClobberMemory();
90   }
91   st.SetComplexityN(st.range(0));
92 }
93 BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements,
94   getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
95 
96 
97 template <class GenInputs>
BM_PathIterateOnce(benchmark::State & st,GenInputs gen)98 void BM_PathIterateOnce(benchmark::State &st, GenInputs gen) {
99   using fs::path;
100   const auto in = gen(st.range(0));
101   path PP;
102   for (auto& Part : in)
103     PP /= Part;
104   benchmark::DoNotOptimize(PP.native().data());
105   while (st.KeepRunning()) {
106     const path P = PP.native();
107     for (auto &E : P) {
108       benchmark::DoNotOptimize(E.native().data());
109     }
110     benchmark::ClobberMemory();
111   }
112   st.SetComplexityN(st.range(0));
113 }
114 BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements,
115   getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
116 
117 template <class GenInputs>
BM_PathIterateOnceBackwards(benchmark::State & st,GenInputs gen)118 void BM_PathIterateOnceBackwards(benchmark::State &st, GenInputs gen) {
119   using fs::path;
120   const auto in = gen(st.range(0));
121   path PP;
122   for (auto& Part : in)
123     PP /= Part;
124   benchmark::DoNotOptimize(PP.native().data());
125   while (st.KeepRunning()) {
126     const path P = PP.native();
127     const auto B = P.begin();
128     auto I = P.end();
129     while (I != B) {
130       --I;
131       benchmark::DoNotOptimize(*I);
132     }
133     benchmark::DoNotOptimize(*I);
134   }
135 }
136 BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
137   getRandomStringInputs)->Arg(TestNumInputs);
138 
getRandomPaths(int NumParts,int PathLen)139 static fs::path getRandomPaths(int NumParts, int PathLen) {
140   fs::path Result;
141   while (NumParts--) {
142     std::string Part = getRandomString(PathLen);
143     Result /= Part;
144   }
145   return Result;
146 }
147 
148 template <class GenInput>
BM_LexicallyNormal(benchmark::State & st,GenInput gen,size_t PathLen)149 void BM_LexicallyNormal(benchmark::State &st, GenInput gen, size_t PathLen) {
150   using fs::path;
151   auto In = gen(st.range(0), PathLen);
152   benchmark::DoNotOptimize(&In);
153   while (st.KeepRunning()) {
154     benchmark::DoNotOptimize(In.lexically_normal());
155   }
156   st.SetComplexityN(st.range(0));
157 }
158 BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path,
159   getRandomPaths, /*PathLen*/5)->RangeMultiplier(2)->Range(2, 256)->Complexity();
160 BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path,
161   getRandomPaths, /*PathLen*/32)->RangeMultiplier(2)->Range(2, 256)->Complexity();
162 
163 BENCHMARK_MAIN();
164