1#include "benchmark/benchmark.h"
2#include "GenerateInput.h"
3#include "test_iterators.h"
4#include "filesystem_include.h"
5
6static const size_t TestNumInputs = 1024;
7
8
9template <class GenInputs>
10void 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}
23BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
24  getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
25
26
27template <class GenInputs>
28void 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}
40BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
41  getRandomStringInputs)->Arg(TestNumInputs);
42
43
44template <template <class...> class ItType, class GenInputs>
45void 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}
63template <class GenInputs>
64void BM_PathConstructInputIter(benchmark::State &st, GenInputs gen) {
65  BM_PathConstructIter<cpp17_input_iterator>(st, gen);
66}
67template <class GenInputs>
68void BM_PathConstructForwardIter(benchmark::State &st, GenInputs gen) {
69  BM_PathConstructIter<forward_iterator>(st, gen);
70}
71BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string,
72  getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
73BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string,
74  getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
75
76
77template <class GenInputs>
78void 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}
93BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements,
94  getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
95
96
97template <class GenInputs>
98void 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}
114BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements,
115  getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
116
117template <class GenInputs>
118void 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}
136BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
137  getRandomStringInputs)->Arg(TestNumInputs);
138
139static 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
148template <class GenInput>
149void 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}
158BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path,
159  getRandomPaths, /*PathLen*/5)->RangeMultiplier(2)->Range(2, 256)->Complexity();
160BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path,
161  getRandomPaths, /*PathLen*/32)->RangeMultiplier(2)->Range(2, 256)->Complexity();
162
163BENCHMARK_MAIN();
164