]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
osd: improve hobject_t::to_str() performance
authorRonen Friedman <rfriedma@redhat.com>
Mon, 12 Feb 2024 16:23:15 +0000 (10:23 -0600)
committerRonen Friedman <rfriedma@redhat.com>
Wed, 21 Feb 2024 14:07:06 +0000 (08:07 -0600)
The new version of the code takes only ~70% of the time of the old one.
See https://github.com/ronen-fr/hobjtostr/tree/rf-1 for the code used
to benchmark the performance of this and various other implementations.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
src/common/fmt_common.h
src/common/hobject.cc
src/common/hobject.h
src/include/object_fmt.h
src/include/types.h

index 1a2a6eac93576f89234cab81f323904d0c19c7f9..53ce8a10ddb78445bfa8e64316db123116bb9173 100644 (file)
@@ -7,6 +7,7 @@
 /**
  * \file default fmtlib formatters for specifically-tagged types
  */
+#include <fmt/compile.h>
 #include <fmt/format.h>
 
 /**
index 1aee4cc42546a5705808d1f6ee20ddd6d71e1673..9f8e67f10b8b49141297e1bce272188c8a5b0f0f 100644 (file)
@@ -2,6 +2,8 @@
 // vim: ts=8 sw=2 smarttab
 
 #include <charconv>
+#include <fmt/compile.h>
+#include <fmt/core.h>
 
 #include "hobject.h"
 #include "common/Formatter.h"
@@ -14,23 +16,25 @@ using std::string;
 using ceph::bufferlist;
 using ceph::Formatter;
 
-static void append_escaped(const string &in, string *out)
+namespace {
+void escape_special_chars(const string& in, string* out)
 {
-  for (string::const_iterator i = in.begin(); i != in.end(); ++i) {
-    if (*i == '%') {
+  for (auto c : in) {
+    if (c == '%') {
       out->push_back('%');
       out->push_back('p');
-    } else if (*i == '.') {
+    } else if (c == '.') {
       out->push_back('%');
       out->push_back('e');
-    } else if (*i == '_') {
+    } else if (c == '_') {
       out->push_back('%');
       out->push_back('u');
     } else {
-      out->push_back(*i);
+      out->push_back(c);
     }
   }
 }
+}  // namespace
 
 set<string> hobject_t::get_prefixes(
   uint32_t bits,
@@ -80,33 +84,25 @@ set<string> hobject_t::get_prefixes(
 
 string hobject_t::to_str() const
 {
-  string out;
-
-  char snap_with_hash[1000];
-  char *t = snap_with_hash;
-  const char *end = t + sizeof(snap_with_hash);
-
   uint64_t poolid(pool);
-  t += snprintf(t, end - t, "%.*llX", 16, (long long unsigned)poolid);
-
   uint32_t revhash(get_nibblewise_key_u32());
-  t += snprintf(t, end - t, ".%.*X", 8, revhash);
 
-  if (snap == CEPH_NOSNAP)
-    t += snprintf(t, end - t, ".head");
-  else if (snap == CEPH_SNAPDIR)
-    t += snprintf(t, end - t, ".snapdir");
-  else
-    t += snprintf(t, end - t, ".%llx", (long long unsigned)snap);
-
-  out.append(snap_with_hash, t);
+  string out;
+  if (snap == CEPH_NOSNAP) {
+    out = fmt::format(FMT_COMPILE("{:016X}.{:08X}.head."), poolid, revhash);
+  } else if (snap == CEPH_SNAPDIR) {
+    out = fmt::format(FMT_COMPILE("{:016X}.{:08X}.snapdir."), poolid, revhash);
+  } else {
+    out = fmt::format(
+       FMT_COMPILE("{:016X}.{:08X}.{:X}."), poolid, revhash,
+       (unsigned long long)snap);
+  }
 
+  escape_special_chars(oid.name, &out);
   out.push_back('.');
-  append_escaped(oid.name, &out);
-  out.push_back('.');
-  append_escaped(get_key(), &out);
+  escape_special_chars(get_key(), &out);
   out.push_back('.');
-  append_escaped(nspace, &out);
+  escape_special_chars(nspace, &out);
 
   return out;
 }
index e35e2b0732f6b9ea8ece8d243c82b1ea7aabec71..fe7f9a705c9814317cf42834d2df7482d3c3dd98 100644 (file)
@@ -318,7 +318,7 @@ public:
   void dump(ceph::Formatter *f) const;
   static void generate_test_instances(std::list<hobject_t*>& o);
   friend int cmp(const hobject_t& l, const hobject_t& r);
-  auto operator<=>(const hobject_t &rhs) const noexcept {
+  constexpr auto operator<=>(const hobject_t &rhs) const noexcept {
     auto cmp = max <=> rhs.max;
     if (cmp != 0) return cmp;
     cmp = pool <=> rhs.pool;
@@ -335,7 +335,7 @@ public:
     if (cmp != 0) return cmp;
     return snap <=> rhs.snap;
   }
-  bool operator==(const hobject_t& rhs) const noexcept {
+  constexpr bool operator==(const hobject_t& rhs) const noexcept {
     return operator<=>(rhs) == 0;
   }
   friend struct ghobject_t;
@@ -495,7 +495,7 @@ struct ghobject_t {
   void dump(ceph::Formatter *f) const;
   static void generate_test_instances(std::list<ghobject_t*>& o);
   friend int cmp(const ghobject_t& l, const ghobject_t& r);
-  auto operator<=>(const ghobject_t&) const = default;
+  constexpr auto operator<=>(const ghobject_t&) const = default;
   bool operator==(const ghobject_t&) const = default;
 };
 WRITE_CLASS_ENCODER(ghobject_t)
index 33df5e3fbd99e9b57548447428fc0bd65421ff94..25fbc6714c8ef4fa2887c243eab72e90bb0193b3 100644 (file)
@@ -5,6 +5,7 @@
 /**
  * \file fmtlib formatters for some object.h structs
  */
+#include <fmt/compile.h>
 #include <fmt/format.h>
 
 #include "object.h"
@@ -24,6 +25,6 @@ struct fmt::formatter<snapid_t> {
     if (snp == CEPH_SNAPDIR) {
       return fmt::format_to(ctx.out(), "snapdir");
     }
-    return fmt::format_to(ctx.out(), "{:x}", snp.val);
+    return fmt::format_to(ctx.out(), FMT_COMPILE("{:x}"), snp.val);
   }
 };
index a50a506eb0bc265cd1da5d832334876ec461ee3d..b3777d9de4fdd6965ab4d65400ddba4bd59dbc9a 100644 (file)
@@ -513,7 +513,7 @@ struct shard_id_t {
   shard_id_t() : id(0) {}
   constexpr explicit shard_id_t(int8_t _id) : id(_id) {}
 
-  operator int8_t() const { return id; }
+  constexpr operator int8_t() const { return id; }
 
   const static shard_id_t NO_SHARD;