From: Piotr Dałek Date: Thu, 25 Jun 2015 12:18:31 +0000 (+0200) Subject: bufferlist: tuning small appends X-Git-Tag: v9.1.0~333^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=03877d683df55d04db6950df24899c1b9e8bb6b9;p=ceph.git bufferlist: tuning small appends 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 --- diff --git a/src/common/buffer.cc b/src/common/buffer.cc index fabaa89e93c9..1295aea5ce05 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -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); diff --git a/src/include/buffer.h b/src/include/buffer.h index d75ebf0d3102..3ff04063783a 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -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);