]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/StackStringStream: optimize xsputn() and overflow() 25814/head
authorKefu Chai <kchai@redhat.com>
Mon, 7 Jan 2019 13:45:08 +0000 (21:45 +0800)
committerKefu Chai <kchai@redhat.com>
Wed, 9 Jan 2019 14:15:12 +0000 (22:15 +0800)
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 <kchai@redhat.com>
src/common/StackStringStream.h

index c59f7d820c177ca858e8e3aa06aafcf85ca9145a..475a23c4fd939ec6a00c7674ee0a1fa456eef852 100644 (file)
@@ -18,7 +18,6 @@
 #include <boost/container/small_vector.hpp>
 
 #include <algorithm>
-#include <cstring>
 #include <iostream>
 #include <memory>
 #include <ostream>
 #include <string_view>
 #include <vector>
 
+#include "include/inline_memory.h"
+
 template<std::size_t SIZE>
 class StackStringBuf : public std::basic_streambuf<char>
 {
 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: