]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
memstore: use thread_local page vector 5622/head
authorCasey Bodley <cbodley@redhat.com>
Wed, 5 Aug 2015 20:20:38 +0000 (16:20 -0400)
committerCasey Bodley <cbodley@redhat.com>
Thu, 27 Aug 2015 16:32:40 +0000 (12:32 -0400)
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 <cbodley@redhat.com>
src/os/MemStore.cc
src/os/MemStore.h

index efa2b8aefcdca3ce5f97348515b78b51d113b1f9..a098f315994f7f687a494f75a141221460ae893d 100644 (file)
@@ -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<bufferlist&>(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;
 }
index 7ffd100e26a91cfde9430f305fdf12eb03a6b496..4725c3445bf130915d8d15206719a89075c9098a 100644 (file)
@@ -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; }