Commit f63b0805 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by facebook-github-bot-9

Improve performance of fbstring copy and move ctors on small strings

Summary: The move constructor of `fbstring` generates a large amount of code, preventing it to be inlined, and it is inefficient for small strings. This diff fixes both problems.

Reviewed By: @yfeldblum

Differential Revision: D2505762
parent 1638d60d
...@@ -290,16 +290,7 @@ protected: ...@@ -290,16 +290,7 @@ protected:
static_assert( static_assert(
kIsLittleEndian || kIsBigEndian, "unable to identify endianness"); kIsLittleEndian || kIsBigEndian, "unable to identify endianness");
public: public:
fbstring_core() noexcept { fbstring_core() noexcept { reset(); }
// Only initialize the tag, will set the MSBs (i.e. the small
// string size) to zero too
ml_.capacity_ = kIsLittleEndian
? maxSmallSize << (8 * (sizeof(size_t) - sizeof(Char)))
: ml_.capacity_ = maxSmallSize << 2;
// or: setSmallSize(0);
writeTerminator();
assert(category() == Category::isSmall && size() == 0);
}
fbstring_core(const fbstring_core & rhs) { fbstring_core(const fbstring_core & rhs) {
assert(&rhs != this); assert(&rhs != this);
...@@ -311,18 +302,12 @@ public: ...@@ -311,18 +302,12 @@ public:
"fbstring layout failure"); "fbstring layout failure");
static_assert(offsetof(MediumLarge, capacity_) == 2 * sizeof(ml_.data_), static_assert(offsetof(MediumLarge, capacity_) == 2 * sizeof(ml_.data_),
"fbstring layout failure"); "fbstring layout failure");
const size_t size = rhs.smallSize();
if (size == 0) {
ml_.capacity_ = rhs.ml_.capacity_;
writeTerminator();
} else {
// Just write the whole thing, don't look at details. In // Just write the whole thing, don't look at details. In
// particular we need to copy capacity anyway because we want // particular we need to copy capacity anyway because we want
// to set the size (don't forget that the last character, // to set the size (don't forget that the last character,
// which stores a short string's length, is shared with the // which stores a short string's length, is shared with the
// ml_.capacity field). // ml_.capacity field).
ml_ = rhs.ml_; ml_ = rhs.ml_;
}
assert(category() == Category::isSmall && this->size() == rhs.size()); assert(category() == Category::isSmall && this->size() == rhs.size());
} else if (rhs.category() == Category::isLarge) { } else if (rhs.category() == Category::isLarge) {
// Large strings are just refcounted // Large strings are just refcounted
...@@ -350,14 +335,11 @@ public: ...@@ -350,14 +335,11 @@ public:
} }
fbstring_core(fbstring_core&& goner) noexcept { fbstring_core(fbstring_core&& goner) noexcept {
if (goner.category() == Category::isSmall) {
// Just copy, leave the goner in peace
new(this) fbstring_core(goner.small_, goner.smallSize());
} else {
// Take goner's guts // Take goner's guts
ml_ = goner.ml_; ml_ = goner.ml_;
if (goner.category() != Category::isSmall) {
// Clean goner's carcass // Clean goner's carcass
goner.setSmallSize(0); goner.reset();
} }
} }
...@@ -463,7 +445,7 @@ public: ...@@ -463,7 +445,7 @@ public:
} else { } else {
// No need for the memory // No need for the memory
free(data); free(data);
setSmallSize(0); reset();
} }
} }
...@@ -723,6 +705,19 @@ private: ...@@ -723,6 +705,19 @@ private:
// Disabled // Disabled
fbstring_core & operator=(const fbstring_core & rhs); fbstring_core & operator=(const fbstring_core & rhs);
// Equivalent to setSmallSize(0), but with specialized
// writeTerminator which doesn't re-check the category after
// capacity_ is overwritten.
void reset() {
// Only initialize the tag, will set the MSBs (i.e. the small
// string size) to zero too.
ml_.capacity_ = kIsLittleEndian
? maxSmallSize << (8 * (sizeof(size_t) - sizeof(Char)))
: maxSmallSize << 2;
small_[0] = '\0';
assert(category() == Category::isSmall && size() == 0);
}
struct RefCounted { struct RefCounted {
std::atomic<size_t> refCount_; std::atomic<size_t> refCount_;
Char data_[1]; Char data_[1];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment