diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 8b8dce5083149..7f5f7ec22585c 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -45,6 +45,7 @@ Improvements and New Features - The performance of ``map::map(const map&)`` has been improved up to 2.3x - The performance of ``map::operator=(const map&)`` has been improved by up to 11x +- Some reallocations are now avoided in `std::filesystem::path::lexically_relative`, resulting in a performance improvement of up to 1.7x. Deprecations and Removals ------------------------- diff --git a/libcxx/src/filesystem/path.cpp b/libcxx/src/filesystem/path.cpp index 9f7dc54fdf156..400b6e8988569 100644 --- a/libcxx/src/filesystem/path.cpp +++ b/libcxx/src/filesystem/path.cpp @@ -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) diff --git a/libcxx/test/benchmarks/filesystem.bench.cpp b/libcxx/test/benchmarks/filesystem.bench.cpp index dc6b0ac537f7e..c058a5d41a150 100644 --- a/libcxx/test/benchmarks/filesystem.bench.cpp +++ b/libcxx/test/benchmarks/filesystem.bench.cpp @@ -171,4 +171,24 @@ BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32 ->Range(2, 256) ->Complexity(); +template +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();