]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
bufferlist: tuning small appends
authorPiotr Dałek <piotr.dalek@ts.fujitsu.com>
Thu, 25 Jun 2015 12:18:31 +0000 (14:18 +0200)
committerPiotr Dałek <piotr.dalek@ts.fujitsu.com>
Tue, 4 Aug 2015 07:56:25 +0000 (09:56 +0200)
This change increases performance of small buffer::list::append and
buffer::ptr::append. In particular, the most common ones (1, 4, 8 and 16
byte appends) are about twice as fast due to direct accessing of data and
decreased call depths for these cases.

Signed-off-by: Piotr Dałek <piotr.dalek@ts.fujitsu.com>
src/common/buffer.cc
src/include/buffer.h

index fabaa89e93c95a4f2838fb54aeeb619c789bdde9..1295aea5ce054472ba73a8322310b120f53fe155 100644 (file)
@@ -817,12 +817,53 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
     _len++;
   }
   
-  void buffer::ptr::append(const char *p, unsigned l)
+  unsigned buffer::ptr::append(const char *p, unsigned l)
   {
     assert(_raw);
     assert(l <= unused_tail_length());
-    memcpy(c_str() + _len, p, l);
-    _len += l;
+    char* c = _raw->data + _off + _len;
+    if (l <= 32) {
+        _len += l;
+        switch (l) {
+            case 16:
+                *((uint64_t*)(c)) = *((uint64_t*)(p));
+                *((uint64_t*)(c+sizeof(uint64_t))) = *((uint64_t*)(p+sizeof(uint64_t)));
+                return _len + _off;
+            case 8:
+                *((uint64_t*)(c)) = *((uint64_t*)(p));
+                return _len + _off;
+            case 4:
+                *((uint32_t*)(c)) = *((uint32_t*)(p));
+                return _len + _off;
+            case 2:
+                *((uint16_t*)(c)) = *((uint16_t*)(p));
+                return _len + _off;
+            case 1:
+                *((uint8_t*)(c)) = *((uint8_t*)(p));
+                return _len + _off;
+        }
+        int cursor = 0;
+        while (l >= sizeof(uint64_t)) {
+            *((uint64_t*)(c + cursor)) = *((uint64_t*)(p + cursor));
+            cursor += sizeof(uint64_t);
+            l -= sizeof(uint64_t);
+        }
+        while (l >= sizeof(uint32_t)) {
+            *((uint32_t*)(c + cursor)) = *((uint32_t*)(p + cursor));
+            cursor += sizeof(uint32_t);
+            l -= sizeof(uint32_t);
+        }
+        while (l > 0) {
+            *(c+cursor) = *(p+cursor);
+            cursor++;
+            l--;
+        }
+    }
+    else {
+        memcpy(c, p, l);
+        _len += l;
+    }
+    return _len + _off;
   }
     
   void buffer::ptr::copy_in(unsigned o, unsigned l, const char *src)
@@ -1383,15 +1424,15 @@ void buffer::list::rebuild_page_aligned()
       // put what we can into the existing append_buffer.
       unsigned gap = append_buffer.unused_tail_length();
       if (gap > 0) {
-       if (gap > len) gap = len;
-       //cout << "append first char is " << data[0] << ", last char is " << data[len-1] << std::endl;
-       append_buffer.append(data, gap);
-       append(append_buffer, append_buffer.end() - gap, gap);  // add segment to the list
-       len -= gap;
-       data += gap;
+        if (gap > len) gap = len;
+    //cout << "append first char is " << data[0] << ", last char is " << data[len-1] << std::endl;
+        append_buffer.append(data, gap);
+        append(append_buffer, append_buffer.end() - gap, gap); // add segment to the list
+        len -= gap;
+        data += gap;
       }
       if (len == 0)
-       break;  // done!
+        break;  // done!
       
       // make a new append_buffer!
       unsigned alen = CEPH_PAGE_SIZE * (((len-1) / CEPH_PAGE_SIZE) + 1);
index d75ebf0d3102e1cd0be8f47ceba97ea43098e548..3ff04063783ae22ccd19299542f0dccf41f316d7 100644 (file)
@@ -245,7 +245,7 @@ public:
     }
 
     void append(char c);
-    void append(const char *p, unsigned l);
+    unsigned append(const char *p, unsigned l);
     void copy_in(unsigned o, unsigned l, const char *src);
     void zero();
     void zero(unsigned o, unsigned l);