]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/LevelDBStore: faster LevelDBTransactionImpl::set
authorPiotr Dałek <piotr.dalek@ts.fujitsu.com>
Tue, 20 Oct 2015 13:11:08 +0000 (15:11 +0200)
committerSage Weil <sage@redhat.com>
Mon, 9 Nov 2015 14:03:22 +0000 (09:03 -0500)
This patch builds on Sage's idea to reduce bufferlist copying on
::set() calls. Initial patch reduced LevelDB's Slice generation
time from ~57ns to ~5ns in best-case scenario (bufferlist with
single bufferptr or contiguous bufferptrs), this patch reduces
slice generation time from ~57ns to ~11ns in worst case scenario
(under assumption that entire value length is at most 128KB),
leaving old code path for extremely-bad cases.

Signed-off-by: Piotr Dałek <piotr.dalek@ts.fujitsu.com>
src/kv/LevelDBStore.cc

index 29d5ae760cd7c9726bfeb7b56f9f5e97a21e9702..829f247d5287f6c2419d2a3f9d89b7747bc35098 100644 (file)
@@ -164,17 +164,28 @@ void LevelDBStore::LevelDBTransactionImpl::set(
   const bufferlist &to_set_bl)
 {
   string key = combine_strings(prefix, k);
-
+  size_t bllen = to_set_bl.length();
   // bufferlist::c_str() is non-constant, so we can't call c_str()
-  if (to_set_bl.is_contiguous() && to_set_bl.length() > 0) {
-    bat.Put(leveldb::Slice(key),
-           leveldb::Slice(to_set_bl.buffers().front().c_str(),
-                          to_set_bl.length()));
+  if (to_set_bl.is_contiguous() && bllen > 0) {
+    // bufferlist contains just one ptr or they're contiguous
+    bat.Put(leveldb::Slice(key), leveldb::Slice(to_set_bl.buffers().front().c_str(), bllen));
+  } else if ((bllen <= 32 * 1024) && (bllen > 0)) {
+    // 2+ bufferptrs that are not contiguopus
+    // allocate buffer on stack and copy bl contents to that buffer
+    // make sure the buffer isn't too large or we might crash here...    
+    char* slicebuf = (char*) alloca(bllen);
+    leveldb::Slice newslice(slicebuf, bllen);
+    std::list<buffer::ptr>::const_iterator pb;
+    for (pb = to_set_bl.buffers().begin(); pb != to_set_bl.buffers().end(); ++pb) {
+      size_t ptrlen = (*pb).length();
+      memcpy((void*)slicebuf, (*pb).c_str(), ptrlen);
+      slicebuf += ptrlen;
+    } 
+    bat.Put(leveldb::Slice(key), newslice);
   } else {
-    // make a copy
+    // 2+ bufferptrs that are not contiguous, and enormous in size
     bufferlist val = to_set_bl;
-    bat.Put(leveldb::Slice(key),
-           leveldb::Slice(val.c_str(), val.length()));
+    bat.Put(leveldb::Slice(key), leveldb::Slice(val.c_str(), val.length()));
   }
 }