From 8d3df9be0949fb5bc9f84af563c0d3501c2fc42f Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 7 Jan 2019 21:45:08 +0800 Subject: [PATCH] common/StackStringStream: optimize xsputn() and overflow() use the internal buffer semantics provided by basic_streambuf, in hope to improve the performance when a single character is inserted into buf. * xsputn(): use memcpy() directly instead of creating a temporary string_view * overflow(): overflow() should be called only if the internal buffer overflows when a single character is put into the streambuf. so we can use the fact that the size of inserted buffer is known, and use push_back() instead. also, please see libstdc++'s implementation of basic_streambuf::sputc(), where __builtin_expect() is used to instruct the compiler that the non-overflow branch is more likely to be chosen. so, we need to optimize for that branch. hence this change. * remove the no-more-used push() method Signed-off-by: Kefu Chai --- src/common/StackStringStream.h | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/common/StackStringStream.h b/src/common/StackStringStream.h index c59f7d820c177..475a23c4fd939 100644 --- a/src/common/StackStringStream.h +++ b/src/common/StackStringStream.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -26,36 +25,50 @@ #include #include +#include "include/inline_memory.h" + template class StackStringBuf : public std::basic_streambuf { public: - StackStringBuf() = default; + StackStringBuf() + : vec{SIZE, boost::container::default_init_t{}} + { + setp(vec.data(), vec.data() + vec.size()); + } StackStringBuf(const StackStringBuf&) = delete; StackStringBuf& operator=(const StackStringBuf&) = delete; StackStringBuf(StackStringBuf&& o) = delete; StackStringBuf& operator=(StackStringBuf&& o) = delete; ~StackStringBuf() override = default; - void push(std::string_view sv) - { - vec.insert(vec.end(), sv.begin(), sv.end()); - } - void clear() { - vec.clear(); + vec.resize(SIZE); + setp(vec.data(), vec.data() + SIZE); } std::string_view strv() const { - return std::string_view(vec.data(), vec.size()); + return std::string_view(pbase(), pptr() - pbase()); } protected: std::streamsize xsputn(const char *s, std::streamsize n) { - push(std::string_view(s, n)); + std::streamsize capacity = epptr() - pptr(); + std::streamsize left = n; + if (capacity >= left) { + maybe_inline_memcpy(pptr(), s, left, 32); + pbump(left); + } else { + maybe_inline_memcpy(pptr(), s, capacity, 64); + s += capacity; + left -= capacity; + vec.insert(vec.end(), s, s + left); + setp(vec.data(), vec.data() + vec.size()); + pbump(vec.size()); + } return n; } @@ -63,10 +76,11 @@ protected: { if (traits_type::not_eof(c)) { char str = traits_type::to_char_type(c); - push(std::string_view(&str, 1)); + vec.push_back(str); return c; + } else { + return traits_type::eof(); } - return EOF; } private: -- 2.39.5