xref: /llvm-project/libcxx/test/benchmarks/filesystem.bench.cpp (revision b2d2494731976ab7aa9702f3134472db694b9332)
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