mirror of
https://github.com/darlinghq/darling-libcxx.git
synced 2024-11-30 07:10:33 +00:00
Improve performance of constructing filesystem::path from strings.
This patch fixes a performance bug when constructing or appending to a path from a string or c-string. Previously we called 'push_back' to append every single character. This caused multiple re-allocation and copies when at most one reallocation is necessary. The new behavior is to simply call `string::append` so it can correctly handle reallocation. For large strings this change is a ~4x improvement. This also makes our path faster to construct than libstdc++'s. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@285530 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
271a19ec19
commit
ad1a12c312
@ -21,10 +21,26 @@ void BM_PathConstructString(benchmark::State &st, GenInputs gen) {
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructString, iterate_elements,
|
||||
BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructCStr(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
const path P(PP.native().c_str());
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
@ -85,6 +101,4 @@ void BM_PathIterateOnceBackwards(benchmark::State &st, GenInputs gen) {
|
||||
BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
|
@ -623,10 +623,10 @@ struct _PathCVT {
|
||||
|
||||
template <>
|
||||
struct _PathCVT<char> {
|
||||
|
||||
template <class _Iter>
|
||||
static void __append_range(string& __dest, _Iter __b, _Iter __e) {
|
||||
for (; __b != __e; ++__b)
|
||||
__dest.push_back(*__b);
|
||||
__dest.append(__b, __e);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
@ -640,7 +640,8 @@ struct _PathCVT<char> {
|
||||
static void __append_source(string& __dest, _Source const& __s)
|
||||
{
|
||||
using _Traits = __is_pathable<_Source>;
|
||||
__append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
|
||||
__append_range(__dest, _Traits::__range_begin(__s),
|
||||
_Traits::__range_end(__s));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,8 +42,7 @@ private:
|
||||
public:
|
||||
PathParser(string_view_t P, string_view_t E, unsigned char S)
|
||||
: Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
|
||||
assert(S != 0);
|
||||
assert(S != PS_BeforeBegin);
|
||||
// S cannot be '0' or PS_BeforeBegin.
|
||||
}
|
||||
|
||||
static PathParser CreateBegin(string_view_t P) noexcept {
|
||||
@ -94,7 +93,6 @@ public:
|
||||
|
||||
case PS_InFilenames: {
|
||||
PosPtr SepEnd = consumeSeparator(Start, End);
|
||||
assert(SepEnd);
|
||||
if (SepEnd != End) {
|
||||
PosPtr TkEnd = consumeName(SepEnd, End);
|
||||
if (TkEnd)
|
||||
@ -131,7 +129,6 @@ public:
|
||||
SepEnd + 1, RStart + 1);
|
||||
} else {
|
||||
PosPtr TkStart = consumeName(RStart, REnd);
|
||||
assert(TkStart);
|
||||
if (TkStart == REnd + 2 && consumeSeparator(TkStart, REnd) == REnd)
|
||||
return makeState(PS_InRootName, Path.data(), RStart + 1);
|
||||
else
|
||||
@ -192,14 +189,10 @@ public:
|
||||
|
||||
private:
|
||||
void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
|
||||
assert(NewState != PS_BeforeBegin && NewState != PS_AtEnd);
|
||||
State = NewState;
|
||||
assert(Start < End);
|
||||
assert(Start >= &Path.front() && End <= &Path.back() + 1);
|
||||
RawEntry = string_view_t(Start, End - Start);
|
||||
}
|
||||
void makeState(ParserState NewState) noexcept {
|
||||
assert(NewState == PS_BeforeBegin || NewState == PS_AtEnd);
|
||||
State = NewState;
|
||||
RawEntry = {};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user