From: Casey Bodley Date: Wed, 5 Aug 2015 20:20:38 +0000 (-0400) Subject: memstore: use thread_local page vector X-Git-Tag: v9.1.0~253^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d43c10e0af00c638a07f7501f4926e4bc3b24dfd;p=ceph.git memstore: use thread_local page vector avoid allocating page_vector storage for every read/write request. this improves the sequential write bandwidth in osbench by 5-10% Signed-off-by: Casey Bodley --- diff --git a/src/os/MemStore.cc b/src/os/MemStore.cc index efa2b8aefcdc..a098f315994f 100644 --- a/src/os/MemStore.cc +++ b/src/os/MemStore.cc @@ -327,7 +327,6 @@ int MemStore::read( return o->read(offset, l, bl); } - int MemStore::fiemap(coll_t cid, const ghobject_t& oid, uint64_t offset, size_t len, bufferlist& bl) { @@ -1426,22 +1425,26 @@ int MemStore::BufferlistObject::truncate(uint64_t size) } // PageSetObject + +// use a thread-local vector for the pages returned by PageSet, so we +// can avoid allocations in read/write() +thread_local PageSet::page_vector MemStore::PageSetObject::tls_pages; + int MemStore::PageSetObject::read(uint64_t offset, uint64_t len, bufferlist& bl) { const auto start = offset; const auto end = offset + len; auto remaining = len; - PageSet::page_vector pages; - data.get_range(offset, len, pages); + data.get_range(offset, len, tls_pages); // allocate a buffer for the data buffer::ptr buf(len); - auto p = pages.begin(); + auto p = tls_pages.begin(); while (remaining) { // no more pages in range - if (p == pages.end() || (*p)->offset >= end) { + if (p == tls_pages.end() || (*p)->offset >= end) { buf.zero(offset - start, remaining); break; } @@ -1469,6 +1472,8 @@ int MemStore::PageSetObject::read(uint64_t offset, uint64_t len, bufferlist& bl) ++p; } + tls_pages.clear(); // drop page refs + bl.append(buf); return len; } @@ -1478,10 +1483,9 @@ int MemStore::PageSetObject::write(uint64_t offset, const bufferlist &src) unsigned len = src.length(); // make sure the page range is allocated - PageSet::page_vector pages; - data.alloc_range(offset, src.length(), pages); + data.alloc_range(offset, src.length(), tls_pages); - auto page = pages.begin(); + auto page = tls_pages.begin(); // XXX: cast away the const because bufferlist doesn't have a const_iterator auto p = const_cast(src).begin(); @@ -1497,6 +1501,7 @@ int MemStore::PageSetObject::write(uint64_t offset, const bufferlist &src) } if (data_len < offset) data_len = offset; + tls_pages.clear(); // drop page refs return 0; } @@ -1511,13 +1516,13 @@ int MemStore::PageSetObject::clone(Object *src, uint64_t srcoff, auto &dst_data = data; const auto dst_page_size = dst_data.get_page_size(); - PageSet::page_vector src_pages, dst_pages; + PageSet::page_vector dst_pages; while (len) { const auto count = std::min(len, src_page_size * 16); - src_data.get_range(srcoff, count, src_pages); + src_data.get_range(srcoff, count, tls_pages); - for (auto &src_page : src_pages) { + for (auto &src_page : tls_pages) { auto sbegin = std::max(srcoff, src_page->offset); auto send = std::min(srcoff + count, src_page->offset + src_page_size); dst_data.alloc_range(sbegin + delta, send - sbegin, dst_pages); @@ -1536,7 +1541,7 @@ int MemStore::PageSetObject::clone(Object *src, uint64_t srcoff, dstoff += count; len -= count; } - src_pages.clear(); // drop page refs + tls_pages.clear(); // drop page refs } // update object size @@ -1556,13 +1561,13 @@ int MemStore::PageSetObject::truncate(uint64_t size) return 0; // write zeroes to the rest of the last page - PageSet::page_vector pages; - data.get_range(page_offset, page_size, pages); - if (pages.empty()) + data.get_range(page_offset, page_size, tls_pages); + if (tls_pages.empty()) return 0; - auto page = pages.begin(); + auto page = tls_pages.begin(); auto data = (*page)->data; std::fill(data + (size - page_offset), data + page_size, 0); + tls_pages.clear(); // drop page ref return 0; } diff --git a/src/os/MemStore.h b/src/os/MemStore.h index 7ffd100e26a9..4725c3445bf1 100644 --- a/src/os/MemStore.h +++ b/src/os/MemStore.h @@ -125,6 +125,10 @@ public: PageSet data; size_t data_len; + // use a thread-local vector for the pages returned by PageSet, so we + // can avoid allocations in read/write() + static thread_local PageSet::page_vector tls_pages; + PageSetObject(size_t page_size) : data(page_size), data_len(0) {} size_t get_size() const override { return data_len; }