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