Skip to content
4 changes: 3 additions & 1 deletion libcxx/src/filesystem/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ path path::lexically_relative(const path& base) const {
// return a path constructed with 'n' dot-dot elements, followed by the
// elements of '*this' after the mismatch.
path Result;
// FIXME: Reserve enough room in Result that it won't have to re-allocate.
constexpr size_t ElemSize = 2; // ".."
constexpr size_t SeparatorSize = 1; // separator is always a single char
Result.__reserve(ElemCount * (ElemSize + SeparatorSize) + SeparatorSize + PP.Path.size());
while (ElemCount--)
Result /= PATHSTR("..");
for (; PP; ++PP)
Expand Down
21 changes: 21 additions & 0 deletions libcxx/test/benchmarks/filesystem.bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,25 @@ BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32
->Range(2, 256)
->Complexity();

template <class GenInput>
void BM_LexicallyRelative(benchmark::State& st, GenInput gen, size_t PathLen) {
using fs::path;
auto BasePath = gen(st.range(0), PathLen);
auto TargetPath = gen(st.range(0), PathLen);
benchmark::DoNotOptimize(&BasePath);
benchmark::DoNotOptimize(&TargetPath);
while (st.KeepRunning()) {
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();