xref: /llvm-project/libcxx/test/benchmarks/filesystem.bench.cpp (revision b2d2494731976ab7aa9702f3134472db694b9332)
16a54dfbfSLouis Dionne //===----------------------------------------------------------------------===//
26a54dfbfSLouis Dionne //
36a54dfbfSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46a54dfbfSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
56a54dfbfSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66a54dfbfSLouis Dionne //
76a54dfbfSLouis Dionne //===----------------------------------------------------------------------===//
86a54dfbfSLouis Dionne 
9*b2d24947SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10*b2d24947SLouis Dionne 
1178b4b5ccSLouis Dionne #include <filesystem>
1278b4b5ccSLouis Dionne 
1378b4b5ccSLouis Dionne #include "GenerateInput.h"
1478b4b5ccSLouis Dionne #include "benchmark/benchmark.h"
1578b4b5ccSLouis Dionne #include "test_iterators.h"
1678b4b5ccSLouis Dionne 
1778b4b5ccSLouis Dionne namespace fs = std::filesystem;
1878b4b5ccSLouis Dionne 
1978b4b5ccSLouis Dionne static const size_t TestNumInputs = 1024;
2078b4b5ccSLouis Dionne 
2178b4b5ccSLouis Dionne template <class GenInputs>
2278b4b5ccSLouis Dionne void BM_PathConstructString(benchmark::State& st, GenInputs gen) {
2378b4b5ccSLouis Dionne   using fs::path;
2478b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
2578b4b5ccSLouis Dionne   path PP;
2678b4b5ccSLouis Dionne   for (auto& Part : in)
2778b4b5ccSLouis Dionne     PP /= Part;
2878b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
2978b4b5ccSLouis Dionne   while (st.KeepRunning()) {
3078b4b5ccSLouis Dionne     const path P(PP.native());
3178b4b5ccSLouis Dionne     benchmark::DoNotOptimize(P.native().data());
3278b4b5ccSLouis Dionne   }
3378b4b5ccSLouis Dionne   st.SetComplexityN(st.range(0));
3478b4b5ccSLouis Dionne }
3578b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathConstructString, large_string, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
3678b4b5ccSLouis Dionne 
3778b4b5ccSLouis Dionne template <class GenInputs>
3878b4b5ccSLouis Dionne void BM_PathConstructCStr(benchmark::State& st, GenInputs gen) {
3978b4b5ccSLouis Dionne   using fs::path;
4078b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
4178b4b5ccSLouis Dionne   path PP;
4278b4b5ccSLouis Dionne   for (auto& Part : in)
4378b4b5ccSLouis Dionne     PP /= Part;
4478b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
4578b4b5ccSLouis Dionne   while (st.KeepRunning()) {
4678b4b5ccSLouis Dionne     const path P(PP.native().c_str());
4778b4b5ccSLouis Dionne     benchmark::DoNotOptimize(P.native().data());
4878b4b5ccSLouis Dionne   }
4978b4b5ccSLouis Dionne }
5078b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string, getRandomStringInputs)->Arg(TestNumInputs);
5178b4b5ccSLouis Dionne 
5278b4b5ccSLouis Dionne template <template <class...> class ItType, class GenInputs>
5378b4b5ccSLouis Dionne void BM_PathConstructIter(benchmark::State& st, GenInputs gen) {
5478b4b5ccSLouis Dionne   using fs::path;
5578b4b5ccSLouis Dionne   using Iter    = ItType<std::string::const_iterator>;
5678b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
5778b4b5ccSLouis Dionne   path PP;
5878b4b5ccSLouis Dionne   for (auto& Part : in)
5978b4b5ccSLouis Dionne     PP /= Part;
6078b4b5ccSLouis Dionne   auto Start = Iter(PP.native().begin());
6178b4b5ccSLouis Dionne   auto End   = Iter(PP.native().end());
6278b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
6378b4b5ccSLouis Dionne   benchmark::DoNotOptimize(Start);
6478b4b5ccSLouis Dionne   benchmark::DoNotOptimize(End);
6578b4b5ccSLouis Dionne   while (st.KeepRunning()) {
6678b4b5ccSLouis Dionne     const path P(Start, End);
6778b4b5ccSLouis Dionne     benchmark::DoNotOptimize(P.native().data());
6878b4b5ccSLouis Dionne   }
6978b4b5ccSLouis Dionne   st.SetComplexityN(st.range(0));
7078b4b5ccSLouis Dionne }
7178b4b5ccSLouis Dionne template <class GenInputs>
7278b4b5ccSLouis Dionne void BM_PathConstructInputIter(benchmark::State& st, GenInputs gen) {
7378b4b5ccSLouis Dionne   BM_PathConstructIter<cpp17_input_iterator>(st, gen);
7478b4b5ccSLouis Dionne }
7578b4b5ccSLouis Dionne template <class GenInputs>
7678b4b5ccSLouis Dionne void BM_PathConstructForwardIter(benchmark::State& st, GenInputs gen) {
7778b4b5ccSLouis Dionne   BM_PathConstructIter<forward_iterator>(st, gen);
7878b4b5ccSLouis Dionne }
7978b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string, getRandomStringInputs)
8078b4b5ccSLouis Dionne     ->Range(8, TestNumInputs)
8178b4b5ccSLouis Dionne     ->Complexity();
8278b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string, getRandomStringInputs)
8378b4b5ccSLouis Dionne     ->Range(8, TestNumInputs)
8478b4b5ccSLouis Dionne     ->Complexity();
8578b4b5ccSLouis Dionne 
8678b4b5ccSLouis Dionne template <class GenInputs>
8778b4b5ccSLouis Dionne void BM_PathIterateMultipleTimes(benchmark::State& st, GenInputs gen) {
8878b4b5ccSLouis Dionne   using fs::path;
8978b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
9078b4b5ccSLouis Dionne   path PP;
9178b4b5ccSLouis Dionne   for (auto& Part : in)
9278b4b5ccSLouis Dionne     PP /= Part;
9378b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
9478b4b5ccSLouis Dionne   while (st.KeepRunning()) {
9578b4b5ccSLouis Dionne     for (auto const& E : PP) {
9678b4b5ccSLouis Dionne       benchmark::DoNotOptimize(E.native().data());
9778b4b5ccSLouis Dionne     }
9878b4b5ccSLouis Dionne     benchmark::ClobberMemory();
9978b4b5ccSLouis Dionne   }
10078b4b5ccSLouis Dionne   st.SetComplexityN(st.range(0));
10178b4b5ccSLouis Dionne }
10278b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements, getRandomStringInputs)
10378b4b5ccSLouis Dionne     ->Range(8, TestNumInputs)
10478b4b5ccSLouis Dionne     ->Complexity();
10578b4b5ccSLouis Dionne 
10678b4b5ccSLouis Dionne template <class GenInputs>
10778b4b5ccSLouis Dionne void BM_PathIterateOnce(benchmark::State& st, GenInputs gen) {
10878b4b5ccSLouis Dionne   using fs::path;
10978b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
11078b4b5ccSLouis Dionne   path PP;
11178b4b5ccSLouis Dionne   for (auto& Part : in)
11278b4b5ccSLouis Dionne     PP /= Part;
11378b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
11478b4b5ccSLouis Dionne   while (st.KeepRunning()) {
11578b4b5ccSLouis Dionne     const path P = PP.native();
11678b4b5ccSLouis Dionne     for (auto const& E : P) {
11778b4b5ccSLouis Dionne       benchmark::DoNotOptimize(E.native().data());
11878b4b5ccSLouis Dionne     }
11978b4b5ccSLouis Dionne     benchmark::ClobberMemory();
12078b4b5ccSLouis Dionne   }
12178b4b5ccSLouis Dionne   st.SetComplexityN(st.range(0));
12278b4b5ccSLouis Dionne }
12378b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
12478b4b5ccSLouis Dionne 
12578b4b5ccSLouis Dionne template <class GenInputs>
12678b4b5ccSLouis Dionne void BM_PathIterateOnceBackwards(benchmark::State& st, GenInputs gen) {
12778b4b5ccSLouis Dionne   using fs::path;
12878b4b5ccSLouis Dionne   const auto in = gen(st.range(0));
12978b4b5ccSLouis Dionne   path PP;
13078b4b5ccSLouis Dionne   for (auto& Part : in)
13178b4b5ccSLouis Dionne     PP /= Part;
13278b4b5ccSLouis Dionne   benchmark::DoNotOptimize(PP.native().data());
13378b4b5ccSLouis Dionne   while (st.KeepRunning()) {
13478b4b5ccSLouis Dionne     const path P = PP.native();
13578b4b5ccSLouis Dionne     const auto B = P.begin();
13678b4b5ccSLouis Dionne     auto I       = P.end();
13778b4b5ccSLouis Dionne     while (I != B) {
13878b4b5ccSLouis Dionne       --I;
13978b4b5ccSLouis Dionne       benchmark::DoNotOptimize(*I);
14078b4b5ccSLouis Dionne     }
14178b4b5ccSLouis Dionne     benchmark::DoNotOptimize(*I);
14278b4b5ccSLouis Dionne   }
14378b4b5ccSLouis Dionne }
14478b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements, getRandomStringInputs)->Arg(TestNumInputs);
14578b4b5ccSLouis Dionne 
14678b4b5ccSLouis Dionne static fs::path getRandomPaths(int NumParts, int PathLen) {
14778b4b5ccSLouis Dionne   fs::path Result;
14878b4b5ccSLouis Dionne   while (NumParts--) {
14978b4b5ccSLouis Dionne     std::string Part = getRandomString(PathLen);
15078b4b5ccSLouis Dionne     Result /= Part;
15178b4b5ccSLouis Dionne   }
15278b4b5ccSLouis Dionne   return Result;
15378b4b5ccSLouis Dionne }
15478b4b5ccSLouis Dionne 
15578b4b5ccSLouis Dionne template <class GenInput>
15678b4b5ccSLouis Dionne void BM_LexicallyNormal(benchmark::State& st, GenInput gen, size_t PathLen) {
15778b4b5ccSLouis Dionne   using fs::path;
15878b4b5ccSLouis Dionne   auto In = gen(st.range(0), PathLen);
15978b4b5ccSLouis Dionne   benchmark::DoNotOptimize(&In);
16078b4b5ccSLouis Dionne   while (st.KeepRunning()) {
16178b4b5ccSLouis Dionne     benchmark::DoNotOptimize(In.lexically_normal());
16278b4b5ccSLouis Dionne   }
16378b4b5ccSLouis Dionne   st.SetComplexityN(st.range(0));
16478b4b5ccSLouis Dionne }
16578b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path, getRandomPaths, /*PathLen*/ 5)
16678b4b5ccSLouis Dionne     ->RangeMultiplier(2)
16778b4b5ccSLouis Dionne     ->Range(2, 256)
16878b4b5ccSLouis Dionne     ->Complexity();
16978b4b5ccSLouis Dionne BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32)
17078b4b5ccSLouis Dionne     ->RangeMultiplier(2)
17178b4b5ccSLouis Dionne     ->Range(2, 256)
17278b4b5ccSLouis Dionne     ->Complexity();
17378b4b5ccSLouis Dionne 
17478b4b5ccSLouis Dionne BENCHMARK_MAIN();
175