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