From: Piotr Dałek Date: Tue, 20 Oct 2015 13:11:08 +0000 (+0200) Subject: os/LevelDBStore: faster LevelDBTransactionImpl::set X-Git-Tag: v10.0.1~116^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e184ca23396ed1f8fbaa854af06c9191bfb6264b;p=ceph.git os/LevelDBStore: faster LevelDBTransactionImpl::set 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 --- diff --git a/src/kv/LevelDBStore.cc b/src/kv/LevelDBStore.cc index 29d5ae760cd7..829f247d5287 100644 --- a/src/kv/LevelDBStore.cc +++ b/src/kv/LevelDBStore.cc @@ -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::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())); } }