Skip to content

Commit d282452

Browse files
[libc++] Avoid string reallocation in std::filesystem::path::lexically_relative (#152964)
Improves runtime by around 20 to 40%. (1.3x to 1.7x) ``` Benchmark Time CPU Time Old Time New CPU Old CPU New ------------------------------------------------------------------------------------------------------------------------------------------------ BM_LexicallyRelative/small_path/2 -0.2111 -0.2082 229 181 228 180 BM_LexicallyRelative/small_path/4 -0.2579 -0.2550 455 338 452 337 BM_LexicallyRelative/small_path/8 -0.2643 -0.2616 844 621 838 619 BM_LexicallyRelative/small_path/16 -0.2582 -0.2556 1562 1158 1551 1155 BM_LexicallyRelative/small_path/32 -0.2518 -0.2496 3023 2262 3004 2254 BM_LexicallyRelative/small_path/64 -0.2806 -0.2775 6344 4564 6295 4549 BM_LexicallyRelative/small_path/128 -0.2165 -0.2137 11762 9216 11683 9186 BM_LexicallyRelative/small_path/256 -0.2672 -0.2645 24499 17953 24324 17891 BM_LexicallyRelative/large_path/2 -0.3268 -0.3236 426 287 422 285 BM_LexicallyRelative/large_path/4 -0.3274 -0.3248 734 494 729 492 BM_LexicallyRelative/large_path/8 -0.3586 -0.3560 1409 904 1399 901 BM_LexicallyRelative/large_path/16 -0.3978 -0.3951 2764 1665 2743 1659 BM_LexicallyRelative/large_path/32 -0.3934 -0.3908 5323 3229 5283 3218 BM_LexicallyRelative/large_path/64 -0.3629 -0.3605 10340 6587 10265 6564 BM_LexicallyRelative/large_path/128 -0.3450 -0.3423 19379 12694 19233 12649 BM_LexicallyRelative/large_path/256 -0.3097 -0.3054 36293 25052 35943 24965 ``` --------- Co-authored-by: Nikolas Klauser <[email protected]>
1 parent 30fcf69 commit d282452

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Improvements and New Features
5050
- The performance of ``unordered_set::operator=(const unordered_set&)`` has been improved by up to 5x.
5151
- The performance of ``map::erase`` and ``set::erase`` has been improved by up to 2x
5252
- The performance of ``find(key)`` in ``map``, ``set``, ``multimap`` and ``multiset`` has been improved by up to 2.3x
53+
- Some reallocations are now avoided in `std::filesystem::path::lexically_relative`, resulting in a performance improvement of up to 1.7x.
5354

5455
Deprecations and Removals
5556
-------------------------

libcxx/src/filesystem/path.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ path path::lexically_relative(const path& base) const {
292292
// return a path constructed with 'n' dot-dot elements, followed by the
293293
// elements of '*this' after the mismatch.
294294
path Result;
295-
// FIXME: Reserve enough room in Result that it won't have to re-allocate.
295+
constexpr size_t ElemSize = 2; // ".."
296+
constexpr size_t SeparatorSize = 1; // separator is always a single char
297+
Result.__reserve(ElemCount * (ElemSize + SeparatorSize) + SeparatorSize + PP.Path.size());
296298
while (ElemCount--)
297299
Result /= PATHSTR("..");
298300
for (; PP; ++PP)

libcxx/test/benchmarks/filesystem.bench.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,24 @@ BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path, getRandomPaths, /*PathLen*/ 32
171171
->Range(2, 256)
172172
->Complexity();
173173

174+
template <class GenInput>
175+
void BM_LexicallyRelative(benchmark::State& st, GenInput gen, size_t PathLen) {
176+
auto BasePath = gen(st.range(0), PathLen);
177+
auto TargetPath = gen(st.range(0), PathLen);
178+
benchmark::DoNotOptimize(&BasePath);
179+
benchmark::DoNotOptimize(&TargetPath);
180+
for (auto _ : st) {
181+
benchmark::DoNotOptimize(TargetPath.lexically_relative(BasePath));
182+
}
183+
st.SetComplexityN(st.range(0));
184+
}
185+
BENCHMARK_CAPTURE(BM_LexicallyRelative, small_path, getRandomPaths, /*PathLen*/ 5)
186+
->RangeMultiplier(2)
187+
->Range(2, 256)
188+
->Complexity();
189+
BENCHMARK_CAPTURE(BM_LexicallyRelative, large_path, getRandomPaths, /*PathLen*/ 32)
190+
->RangeMultiplier(2)
191+
->Range(2, 256)
192+
->Complexity();
193+
174194
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)