Skip to content

Commit e462f76

Browse files
committed
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 <[email protected]>
1 parent f912e90 commit e462f76

File tree

5 files changed

+30
-32
lines changed

5 files changed

+30
-32
lines changed

src/common/fmt_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
/**
88
* \file default fmtlib formatters for specifically-tagged types
99
*/
10+
#include <fmt/compile.h>
1011
#include <fmt/format.h>
1112

1213
/**

src/common/hobject.cc

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// vim: ts=8 sw=2 smarttab
33

44
#include <charconv>
5+
#include <fmt/compile.h>
6+
#include <fmt/core.h>
57

68
#include "hobject.h"
79
#include "common/Formatter.h"
@@ -14,23 +16,25 @@ using std::string;
1416
using ceph::bufferlist;
1517
using ceph::Formatter;
1618

17-
static void append_escaped(const string &in, string *out)
19+
namespace {
20+
void escape_special_chars(const string& in, string* out)
1821
{
19-
for (string::const_iterator i = in.begin(); i != in.end(); ++i) {
20-
if (*i == '%') {
22+
for (auto c : in) {
23+
if (c == '%') {
2124
out->push_back('%');
2225
out->push_back('p');
23-
} else if (*i == '.') {
26+
} else if (c == '.') {
2427
out->push_back('%');
2528
out->push_back('e');
26-
} else if (*i == '_') {
29+
} else if (c == '_') {
2730
out->push_back('%');
2831
out->push_back('u');
2932
} else {
30-
out->push_back(*i);
33+
out->push_back(c);
3134
}
3235
}
3336
}
37+
} // namespace
3438

3539
set<string> hobject_t::get_prefixes(
3640
uint32_t bits,
@@ -80,33 +84,25 @@ set<string> hobject_t::get_prefixes(
8084

8185
string hobject_t::to_str() const
8286
{
83-
string out;
84-
85-
char snap_with_hash[1000];
86-
char *t = snap_with_hash;
87-
const char *end = t + sizeof(snap_with_hash);
88-
8987
uint64_t poolid(pool);
90-
t += snprintf(t, end - t, "%.*llX", 16, (long long unsigned)poolid);
91-
9288
uint32_t revhash(get_nibblewise_key_u32());
93-
t += snprintf(t, end - t, ".%.*X", 8, revhash);
9489

95-
if (snap == CEPH_NOSNAP)
96-
t += snprintf(t, end - t, ".head");
97-
else if (snap == CEPH_SNAPDIR)
98-
t += snprintf(t, end - t, ".snapdir");
99-
else
100-
t += snprintf(t, end - t, ".%llx", (long long unsigned)snap);
101-
102-
out.append(snap_with_hash, t);
90+
string out;
91+
if (snap == CEPH_NOSNAP) {
92+
out = fmt::format(FMT_COMPILE("{:016X}.{:08X}.head."), poolid, revhash);
93+
} else if (snap == CEPH_SNAPDIR) {
94+
out = fmt::format(FMT_COMPILE("{:016X}.{:08X}.snapdir."), poolid, revhash);
95+
} else {
96+
out = fmt::format(
97+
FMT_COMPILE("{:016X}.{:08X}.{:X}."), poolid, revhash,
98+
(unsigned long long)snap);
99+
}
103100

101+
escape_special_chars(oid.name, &out);
104102
out.push_back('.');
105-
append_escaped(oid.name, &out);
106-
out.push_back('.');
107-
append_escaped(get_key(), &out);
103+
escape_special_chars(get_key(), &out);
108104
out.push_back('.');
109-
append_escaped(nspace, &out);
105+
escape_special_chars(nspace, &out);
110106

111107
return out;
112108
}

src/common/hobject.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ struct hobject_t {
318318
void dump(ceph::Formatter *f) const;
319319
static void generate_test_instances(std::list<hobject_t*>& o);
320320
friend int cmp(const hobject_t& l, const hobject_t& r);
321-
auto operator<=>(const hobject_t &rhs) const noexcept {
321+
constexpr auto operator<=>(const hobject_t &rhs) const noexcept {
322322
auto cmp = max <=> rhs.max;
323323
if (cmp != 0) return cmp;
324324
cmp = pool <=> rhs.pool;
@@ -335,7 +335,7 @@ struct hobject_t {
335335
if (cmp != 0) return cmp;
336336
return snap <=> rhs.snap;
337337
}
338-
bool operator==(const hobject_t& rhs) const noexcept {
338+
constexpr bool operator==(const hobject_t& rhs) const noexcept {
339339
return operator<=>(rhs) == 0;
340340
}
341341
friend struct ghobject_t;
@@ -495,7 +495,7 @@ struct ghobject_t {
495495
void dump(ceph::Formatter *f) const;
496496
static void generate_test_instances(std::list<ghobject_t*>& o);
497497
friend int cmp(const ghobject_t& l, const ghobject_t& r);
498-
auto operator<=>(const ghobject_t&) const = default;
498+
constexpr auto operator<=>(const ghobject_t&) const = default;
499499
bool operator==(const ghobject_t&) const = default;
500500
};
501501
WRITE_CLASS_ENCODER(ghobject_t)

src/include/object_fmt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/**
66
* \file fmtlib formatters for some object.h structs
77
*/
8+
#include <fmt/compile.h>
89
#include <fmt/format.h>
910

1011
#include "object.h"
@@ -24,6 +25,6 @@ struct fmt::formatter<snapid_t> {
2425
if (snp == CEPH_SNAPDIR) {
2526
return fmt::format_to(ctx.out(), "snapdir");
2627
}
27-
return fmt::format_to(ctx.out(), "{:x}", snp.val);
28+
return fmt::format_to(ctx.out(), FMT_COMPILE("{:x}"), snp.val);
2829
}
2930
};

src/include/types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ struct shard_id_t {
513513
shard_id_t() : id(0) {}
514514
constexpr explicit shard_id_t(int8_t _id) : id(_id) {}
515515

516-
operator int8_t() const { return id; }
516+
constexpr operator int8_t() const { return id; }
517517

518518
const static shard_id_t NO_SHARD;
519519

0 commit comments

Comments
 (0)