]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/ObjectStore: implement more efficient get_encoded_bytes()
authorPiotr Dałek <piotr.dalek@ts.fujitsu.com>
Mon, 22 Feb 2016 12:33:43 +0000 (13:33 +0100)
committerPiotr Dałek <piotr.dalek@ts.fujitsu.com>
Wed, 24 Feb 2016 12:31:17 +0000 (13:31 +0100)
Previous version explicitly encoded entire transaction just to get
its length, which resulted in encoding it twice. New method adds
encoded_size() methods to ghobject_t and coll_t, which return their
encoded size without explicit encoding, and in turn, reducing memory
manager pressure and CPU time spent.

Signed-off-by: Piotr Dałek <piotr.dalek@ts.fujitsu.com>
src/common/hobject.cc
src/common/hobject.h
src/os/ObjectStore.h
src/osd/osd_types.cc
src/osd/osd_types.h

index 17aecd9379a447ed0005b15cbde92f66edbf6aaa..a58a2f015774f59f830eac9cb1cd87c57183df74 100644 (file)
@@ -384,6 +384,7 @@ int cmp_bitwise(const hobject_t& l, const hobject_t& r)
 // version 5.
 void ghobject_t::encode(bufferlist& bl) const
 {
+  // when changing this, remember to update encoded_size() too.
   ENCODE_START(6, 3, bl);
   ::encode(hobj.key, bl);
   ::encode(hobj.oid, bl);
@@ -398,6 +399,47 @@ void ghobject_t::encode(bufferlist& bl) const
   ENCODE_FINISH(bl);
 }
 
+size_t ghobject_t::encoded_size() const
+{
+  // this is not in order of encoding or appearance, but rather
+  // in order of known constants first, so it can be (mostly) computed
+  // at compile time.
+  //  - encoding header + 3 string lengths
+  size_t r = sizeof(ceph_le32) + 2 * sizeof(__u8) + 3 * sizeof(__u32);
+
+  // hobj.snap
+  r += sizeof(uint64_t);
+
+  // hobj.hash
+  r += sizeof(uint32_t);
+
+  // hobj.max
+  r += sizeof(bool);
+
+  // hobj.pool
+  r += sizeof(uint64_t);
+
+  // hobj.generation
+  r += sizeof(uint64_t);
+
+  // hobj.shard_id
+  r += sizeof(int8_t);
+
+  // max
+  r += sizeof(bool);
+
+  // hobj.key
+  r += hobj.key.size();
+
+  // hobj.oid
+  r += hobj.oid.name.size();
+
+  // hobj.nspace
+  r += hobj.nspace.size();
+
+  return r;
+}
+
 void ghobject_t::decode(bufferlist::iterator& bl)
 {
   DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
index b823708441acc187a7e9e277d218cb5a1f8882b7..0cc96fb3670028f2448bcf788f50100aa5f1656a 100644 (file)
@@ -442,6 +442,7 @@ public:
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
   void decode(json_spirit::Value& v);
+  size_t encoded_size() const;
   void dump(Formatter *f) const;
   static void generate_test_instances(list<ghobject_t*>& o);
   friend int cmp_nibblewise(const ghobject_t& l, const ghobject_t& r);
index b0b952452ae8bcbcd4fe5d4417708b58e0177eca..f20280a8fafc4184e8ff8efb641ad262352e8263 100644 (file)
@@ -808,15 +808,27 @@ public:
         return 1 + 8 + 8 + 4 + 4 + 4 + 4 + 4 + tbl.length();
       else {
         //layout: data_bl + op_bl + coll_index + object_index + data
-        //TODO: maybe we need better way to get encoded bytes;
-        bufferlist bl;
-        ::encode(coll_index, bl);
-        ::encode(object_index, bl);
 
+        // coll_index size, object_index size and sizeof(transaction_data)
+        // all here, so they may be computed at compile-time
+        size_t final_size = sizeof(__u32) * 2 + sizeof(data);
+
+        // coll_index second and object_index second
+        final_size += (coll_index.size() + object_index.size()) * sizeof(__le32);
+
+        // coll_index first
+        for (auto p = coll_index.begin(); p != coll_index.end(); ++p) {
+          final_size += p->first.encoded_size();
+        }
+
+        // object_index first
+        for (auto p = object_index.begin(); p != object_index.end(); ++p) {
+          final_size += p->first.encoded_size();
+        }
+        
         return data_bl.length() +
           op_bl.length() +
-          bl.length() +
-          sizeof(data);
+          final_size;
       }
     }
 
index 2d874e5fd8261e36193dd63bcbfbb9afdc821c75..903b6141f325026224af78cb85cf62c54497b895 100644 (file)
@@ -667,6 +667,7 @@ bool coll_t::parse(const std::string& s)
 
 void coll_t::encode(bufferlist& bl) const
 {
+  // when changing this, remember to update encoded_size() too.
   if (is_temp()) {
     // can't express this as v2...
     __u8 struct_v = 3;
@@ -682,6 +683,33 @@ void coll_t::encode(bufferlist& bl) const
   }
 }
 
+size_t coll_t::encoded_size() const
+{
+  size_t r = sizeof(__u8);
+  if (is_temp()) {
+    // v3
+    r += sizeof(__u32);
+    if (_str) {
+      r += strlen(_str);
+    }
+  } else {
+      // v2
+      // 1. type
+      r += sizeof(__u8);
+      // 2. pgid
+      //  - encoding header
+      r += sizeof(ceph_le32) + 2 * sizeof(__u8);
+      // - pg_t
+      r += sizeof(__u8) + sizeof(uint64_t) + 2 * sizeof(uint32_t);
+      // - shard_id_t
+      r += sizeof(int8_t);
+      // 3. snapid_t
+      r += sizeof(uint64_t);
+  }
+
+  return r;
+}
+
 void coll_t::decode(bufferlist::iterator& bl)
 {
   __u8 struct_v;
index 84770d3e92afb199adeb95936d573c6aa87bd4a1..74a4b1df204efd3208389567d3d607d4da286523 100644 (file)
@@ -624,6 +624,7 @@ public:
 
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
+  size_t encoded_size() const;
 
   inline bool operator==(const coll_t& rhs) const {
     // only compare type if meta