182 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 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}34BENCHMARK_CAPTURE(BM_PathConstructString, large_string, getRandomStringInputs)->Range(8, TestNumInputs);35 36template <class GenInputs>37void BM_PathConstructCStr(benchmark::State& st, GenInputs gen) {38 using fs::path;39 const auto in = gen(st.range(0));40 path PP;41 for (auto& Part : in)42 PP /= Part;43 benchmark::DoNotOptimize(PP.native().data());44 while (st.KeepRunning()) {45 const path P(PP.native().c_str());46 benchmark::DoNotOptimize(P.native().data());47 }48}49BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string, getRandomStringInputs)->Arg(TestNumInputs);50 51template <template <class...> class ItType, class GenInputs>52void BM_PathConstructIter(benchmark::State& st, GenInputs gen) {53 using fs::path;54 using Iter = ItType<std::string::const_iterator>;55 const auto in = gen(st.range(0));56 path PP;57 for (auto& Part : in)58 PP /= Part;59 auto Start = Iter(PP.native().begin());60 auto End = Iter(PP.native().end());61 benchmark::DoNotOptimize(PP.native().data());62 benchmark::DoNotOptimize(Start);63 benchmark::DoNotOptimize(End);64 while (st.KeepRunning()) {65 const path P(Start, End);66 benchmark::DoNotOptimize(P.native().data());67 }68}69template <class GenInputs>70void BM_PathConstructInputIter(benchmark::State& st, GenInputs gen) {71 BM_PathConstructIter<cpp17_input_iterator>(st, gen);72}73template <class GenInputs>74void BM_PathConstructForwardIter(benchmark::State& st, GenInputs gen) {75 BM_PathConstructIter<forward_iterator>(st, gen);76}77BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string, getRandomStringInputs)78 ->Range(8, TestNumInputs);79BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string, getRandomStringInputs)80 ->Range(8, TestNumInputs);81 82template <class GenInputs>83void BM_PathIterateMultipleTimes(benchmark::State& st, GenInputs gen) {84 using fs::path;85 const auto in = gen(st.range(0));86 path PP;87 for (auto& Part : in)88 PP /= Part;89 benchmark::DoNotOptimize(PP.native().data());90 while (st.KeepRunning()) {91 for (auto const& E : PP) {92 benchmark::DoNotOptimize(E.native().data());93 }94 benchmark::ClobberMemory();95 }96}97BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements, getRandomStringInputs)98 ->Range(8, TestNumInputs);99 100template <class GenInputs>101void BM_PathIterateOnce(benchmark::State& st, GenInputs gen) {102 using fs::path;103 const auto in = gen(st.range(0));104 path PP;105 for (auto& Part : in)106 PP /= Part;107 benchmark::DoNotOptimize(PP.native().data());108 while (st.KeepRunning()) {109 const path P = PP.native();110 for (auto const& E : P) {111 benchmark::DoNotOptimize(E.native().data());112 }113 benchmark::ClobberMemory();114 }115}116BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements, getRandomStringInputs)->Range(8, TestNumInputs);117 118template <class GenInputs>119void BM_PathIterateOnceBackwards(benchmark::State& st, GenInputs gen) {120 using fs::path;121 const auto in = gen(st.range(0));122 path PP;123 for (auto& Part : in)124 PP /= Part;125 benchmark::DoNotOptimize(PP.native().data());126 while (st.KeepRunning()) {127 const path P = PP.native();128 const auto B = P.begin();129 auto I = P.end();130 while (I != B) {131 --I;132 benchmark::DoNotOptimize(*I);133 }134 benchmark::DoNotOptimize(*I);135 }136}137BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements, getRandomStringInputs)->Arg(TestNumInputs);138 139static fs::path getRandomPaths(int NumParts, int PathLen) {140 fs::path Result;141 while (NumParts--) {142 std::string Part = getRandomString(PathLen);143 Result /= Part;144 }145 return Result;146}147 148template <class GenInput>149void BM_LexicallyNormal(benchmark::State& st, GenInput gen, size_t PathLen) {150 using fs::path;151 auto In = gen(st.range(0), PathLen);152 benchmark::DoNotOptimize(&In);153 while (st.KeepRunning()) {154 benchmark::DoNotOptimize(In.lexically_normal());155 }156}157BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path, getRandomPaths, /*PathLen*/ 5)158 ->RangeMultiplier(2)159 ->Range(2, 256);160BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32)161 ->RangeMultiplier(2)162 ->Range(2, 256);163 164template <class GenInput>165void BM_LexicallyRelative(benchmark::State& st, GenInput gen, size_t PathLen) {166 auto BasePath = gen(st.range(0), PathLen);167 auto TargetPath = gen(st.range(0), PathLen);168 benchmark::DoNotOptimize(&BasePath);169 benchmark::DoNotOptimize(&TargetPath);170 for (auto _ : st) {171 benchmark::DoNotOptimize(TargetPath.lexically_relative(BasePath));172 }173}174BENCHMARK_CAPTURE(BM_LexicallyRelative, small_path, getRandomPaths, /*PathLen*/ 5)175 ->RangeMultiplier(2)176 ->Range(2, 256);177BENCHMARK_CAPTURE(BM_LexicallyRelative, large_path, getRandomPaths, /*PathLen*/ 32)178 ->RangeMultiplier(2)179 ->Range(2, 256);180 181BENCHMARK_MAIN();182