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
17namespace fs = std::filesystem;
18
19static const size_t TestNumInputs = 1024;
20
21template <class GenInputs>
22void 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}
35BENCHMARK_CAPTURE(BM_PathConstructString, large_string, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
36
37template <class GenInputs>
38void 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}
50BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string, getRandomStringInputs)->Arg(TestNumInputs);
51
52template <template <class...> class ItType, class GenInputs>
53void 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}
71template <class GenInputs>
72void BM_PathConstructInputIter(benchmark::State& st, GenInputs gen) {
73 BM_PathConstructIter<cpp17_input_iterator>(st, gen);
74}
75template <class GenInputs>
76void BM_PathConstructForwardIter(benchmark::State& st, GenInputs gen) {
77 BM_PathConstructIter<forward_iterator>(st, gen);
78}
79BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string, getRandomStringInputs)
80 ->Range(8, TestNumInputs)
81 ->Complexity();
82BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string, getRandomStringInputs)
83 ->Range(8, TestNumInputs)
84 ->Complexity();
85
86template <class GenInputs>
87void 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}
102BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements, getRandomStringInputs)
103 ->Range(8, TestNumInputs)
104 ->Complexity();
105
106template <class GenInputs>
107void 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}
123BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
124
125template <class GenInputs>
126void 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}
144BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements, getRandomStringInputs)->Arg(TestNumInputs);
145
146static 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
155template <class GenInput>
156void 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}
165BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path, getRandomPaths, /*PathLen*/ 5)
166 ->RangeMultiplier(2)
167 ->Range(2, 256)
168 ->Complexity();
169BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32)
170 ->RangeMultiplier(2)
171 ->Range(2, 256)
172 ->Complexity();
173
174BENCHMARK_MAIN();
175

source code of libcxx/test/benchmarks/filesystem.bench.cpp