Summary:
I noticed that push_back(Char) was slower for fbstring than
for std::string for long strings and found that I could make
it faster by inlining the call to mutable_data() and
exploit that it's always non-small and non-shared.
Benchmarks before:
./folly/test/FBStringTestBenchmarks.cpp.h relative time/iter iters/s
BM_push_back_string(1) 69.42ns 14.41M
BM_push_back_string(23) 582.31ns 1.72M
BM_push_back_string(127) 1.47us 682.12K
BM_push_back_string(1024) 5.52us 181.07K
BM_push_back_fbstring(1) 9.55ns 104.74M
BM_push_back_fbstring(23) 212.45ns 4.71M
BM_push_back_fbstring(127) 864.00ns 1.16M
BM_push_back_fbstring(1024) 6.73us 148.52K
and after:
BM_push_back_fbstring(1) 9.55ns 104.74M
BM_push_back_fbstring(23) 212.45ns 4.71M
BM_push_back_fbstring(127) 783.08ns 1.28M
BM_push_back_fbstring(1024) 4.03us 248.05K
Test Plan: fbconfig folly/test && fbmake runtests
Reviewed By: tudorb@fb.com
FB internal diff:
D646081
void push_back(Char c) {
assert(capacity() >= size());
- size_t sz, cp;
+ size_t sz;
if (category() == isSmall) {
sz = smallSize();
if (sz < maxSmallSize) {
reserve(maxSmallSize * 2);
} else {
sz = ml_.size_;
- cp = capacity(); // != ml_.capacity() for isShared()
- if (sz == cp) reserve(cp * 3 / 2);
+ if (sz == capacity()) { // always true for isShared()
+ reserve(sz * 3 / 2); // ensures not shared
+ }
}
+ assert(!isShared());
assert(capacity() >= sz + 1);
// Category can't be small - we took care of that above
assert(category() == isMedium || category() == isLarge);
ml_.size_ = sz + 1;
- mutable_data()[sz] = c;
+ ml_.data_[sz] = c;
writeTerminator();
}