| //===----------------------------------------------------------------------===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | // UNSUPPORTED: c++03, c++11, c++14, c++17 | 
 |  | 
 | #include <filesystem> | 
 |  | 
 | #include "GenerateInput.h" | 
 | #include "benchmark/benchmark.h" | 
 | #include "test_iterators.h" | 
 |  | 
 | namespace fs = std::filesystem; | 
 |  | 
 | static const size_t TestNumInputs = 1024; | 
 |  | 
 | template <class GenInputs> | 
 | void BM_PathConstructString(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   while (st.KeepRunning()) { | 
 |     const path P(PP.native()); | 
 |     benchmark::DoNotOptimize(P.native().data()); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathConstructString, large_string, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity(); | 
 |  | 
 | template <class GenInputs> | 
 | void BM_PathConstructCStr(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   while (st.KeepRunning()) { | 
 |     const path P(PP.native().c_str()); | 
 |     benchmark::DoNotOptimize(P.native().data()); | 
 |   } | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string, getRandomStringInputs)->Arg(TestNumInputs); | 
 |  | 
 | template <template <class...> class ItType, class GenInputs> | 
 | void BM_PathConstructIter(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   using Iter    = ItType<std::string::const_iterator>; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   auto Start = Iter(PP.native().begin()); | 
 |   auto End   = Iter(PP.native().end()); | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   benchmark::DoNotOptimize(Start); | 
 |   benchmark::DoNotOptimize(End); | 
 |   while (st.KeepRunning()) { | 
 |     const path P(Start, End); | 
 |     benchmark::DoNotOptimize(P.native().data()); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | template <class GenInputs> | 
 | void BM_PathConstructInputIter(benchmark::State& st, GenInputs gen) { | 
 |   BM_PathConstructIter<cpp17_input_iterator>(st, gen); | 
 | } | 
 | template <class GenInputs> | 
 | void BM_PathConstructForwardIter(benchmark::State& st, GenInputs gen) { | 
 |   BM_PathConstructIter<forward_iterator>(st, gen); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string, getRandomStringInputs) | 
 |     ->Range(8, TestNumInputs) | 
 |     ->Complexity(); | 
 | BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string, getRandomStringInputs) | 
 |     ->Range(8, TestNumInputs) | 
 |     ->Complexity(); | 
 |  | 
 | template <class GenInputs> | 
 | void BM_PathIterateMultipleTimes(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   while (st.KeepRunning()) { | 
 |     for (auto const& E : PP) { | 
 |       benchmark::DoNotOptimize(E.native().data()); | 
 |     } | 
 |     benchmark::ClobberMemory(); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements, getRandomStringInputs) | 
 |     ->Range(8, TestNumInputs) | 
 |     ->Complexity(); | 
 |  | 
 | template <class GenInputs> | 
 | void BM_PathIterateOnce(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   while (st.KeepRunning()) { | 
 |     const path P = PP.native(); | 
 |     for (auto const& E : P) { | 
 |       benchmark::DoNotOptimize(E.native().data()); | 
 |     } | 
 |     benchmark::ClobberMemory(); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements, getRandomStringInputs)->Range(8, TestNumInputs)->Complexity(); | 
 |  | 
 | template <class GenInputs> | 
 | void BM_PathIterateOnceBackwards(benchmark::State& st, GenInputs gen) { | 
 |   using fs::path; | 
 |   const auto in = gen(st.range(0)); | 
 |   path PP; | 
 |   for (auto& Part : in) | 
 |     PP /= Part; | 
 |   benchmark::DoNotOptimize(PP.native().data()); | 
 |   while (st.KeepRunning()) { | 
 |     const path P = PP.native(); | 
 |     const auto B = P.begin(); | 
 |     auto I       = P.end(); | 
 |     while (I != B) { | 
 |       --I; | 
 |       benchmark::DoNotOptimize(*I); | 
 |     } | 
 |     benchmark::DoNotOptimize(*I); | 
 |   } | 
 | } | 
 | BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements, getRandomStringInputs)->Arg(TestNumInputs); | 
 |  | 
 | static fs::path getRandomPaths(int NumParts, int PathLen) { | 
 |   fs::path Result; | 
 |   while (NumParts--) { | 
 |     std::string Part = getRandomString(PathLen); | 
 |     Result /= Part; | 
 |   } | 
 |   return Result; | 
 | } | 
 |  | 
 | template <class GenInput> | 
 | void BM_LexicallyNormal(benchmark::State& st, GenInput gen, size_t PathLen) { | 
 |   using fs::path; | 
 |   auto In = gen(st.range(0), PathLen); | 
 |   benchmark::DoNotOptimize(&In); | 
 |   while (st.KeepRunning()) { | 
 |     benchmark::DoNotOptimize(In.lexically_normal()); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path, getRandomPaths, /*PathLen*/ 5) | 
 |     ->RangeMultiplier(2) | 
 |     ->Range(2, 256) | 
 |     ->Complexity(); | 
 | BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32) | 
 |     ->RangeMultiplier(2) | 
 |     ->Range(2, 256) | 
 |     ->Complexity(); | 
 |  | 
 | template <class GenInput> | 
 | void BM_LexicallyRelative(benchmark::State& st, GenInput gen, size_t PathLen) { | 
 |   auto BasePath   = gen(st.range(0), PathLen); | 
 |   auto TargetPath = gen(st.range(0), PathLen); | 
 |   benchmark::DoNotOptimize(&BasePath); | 
 |   benchmark::DoNotOptimize(&TargetPath); | 
 |   for (auto _ : st) { | 
 |     benchmark::DoNotOptimize(TargetPath.lexically_relative(BasePath)); | 
 |   } | 
 |   st.SetComplexityN(st.range(0)); | 
 | } | 
 | BENCHMARK_CAPTURE(BM_LexicallyRelative, small_path, getRandomPaths, /*PathLen*/ 5) | 
 |     ->RangeMultiplier(2) | 
 |     ->Range(2, 256) | 
 |     ->Complexity(); | 
 | BENCHMARK_CAPTURE(BM_LexicallyRelative, large_path, getRandomPaths, /*PathLen*/ 32) | 
 |     ->RangeMultiplier(2) | 
 |     ->Range(2, 256) | 
 |     ->Complexity(); | 
 |  | 
 | BENCHMARK_MAIN(); |