From: Ronen Friedman Date: Mon, 12 Feb 2024 16:23:15 +0000 (-0600) Subject: osd: improve hobject_t::to_str() performance X-Git-Tag: testing/wip-batrick-testing-20240411.154038~384^2~6 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=e462f76aedbb89e8db57dc2324d4f5e9fe54cf9e;p=ceph-ci.git osd: improve hobject_t::to_str() performance 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 --- diff --git a/src/common/fmt_common.h b/src/common/fmt_common.h index 1a2a6eac935..53ce8a10ddb 100644 --- a/src/common/fmt_common.h +++ b/src/common/fmt_common.h @@ -7,6 +7,7 @@ /** * \file default fmtlib formatters for specifically-tagged types */ +#include #include /** diff --git a/src/common/hobject.cc b/src/common/hobject.cc index 1aee4cc4254..9f8e67f10b8 100644 --- a/src/common/hobject.cc +++ b/src/common/hobject.cc @@ -2,6 +2,8 @@ // vim: ts=8 sw=2 smarttab #include +#include +#include #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 hobject_t::get_prefixes( uint32_t bits, @@ -80,33 +84,25 @@ set 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; } diff --git a/src/common/hobject.h b/src/common/hobject.h index e35e2b0732f..fe7f9a705c9 100644 --- a/src/common/hobject.h +++ b/src/common/hobject.h @@ -318,7 +318,7 @@ public: void dump(ceph::Formatter *f) const; static void generate_test_instances(std::list& 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& 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) diff --git a/src/include/object_fmt.h b/src/include/object_fmt.h index 33df5e3fbd9..25fbc6714c8 100644 --- a/src/include/object_fmt.h +++ b/src/include/object_fmt.h @@ -5,6 +5,7 @@ /** * \file fmtlib formatters for some object.h structs */ +#include #include #include "object.h" @@ -24,6 +25,6 @@ struct fmt::formatter { 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); } }; diff --git a/src/include/types.h b/src/include/types.h index a50a506eb0b..b3777d9de4f 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -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;