1 #include "benchmark/benchmark.h" 2 #include "GenerateInput.h" 3 #include "test_iterators.h" 4 #include "filesystem_include.h" 5 6 static const size_t TestNumInputs = 1024; 7 8 9 template <class GenInputs> 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> 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> 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> 64 void BM_PathConstructInputIter(benchmark::State &st, GenInputs gen) { 65 BM_PathConstructIter<cpp17_input_iterator>(st, gen); 66 } 67 template <class GenInputs> 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> 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 const& 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> 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 const& 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> 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 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> 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