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, c++17 |
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(Len: 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 | |