Skip to content

Commit 57f90b1

Browse files
authored
Merge pull request ceph#55583 from ronen-fr/wip-rf-hobject
osd: improve hobject_t::to_str() performance Reviewed-by: Matan Breizman <[email protected]> Reviewed-by: Samuel Just <[email protected]>
2 parents 9bce68a + 94f1cad commit 57f90b1

File tree

17 files changed

+429
-126
lines changed

17 files changed

+429
-126
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: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#ifndef __CEPH_OS_HOBJECT_H
1616
#define __CEPH_OS_HOBJECT_H
1717

18+
#include <fmt/compile.h>
19+
#include <fmt/format.h>
20+
1821
#if FMT_VERSION >= 90000
1922
#include <fmt/ostream.h>
2023
#endif
@@ -318,7 +321,7 @@ struct hobject_t {
318321
void dump(ceph::Formatter *f) const;
319322
static void generate_test_instances(std::list<hobject_t*>& o);
320323
friend int cmp(const hobject_t& l, const hobject_t& r);
321-
auto operator<=>(const hobject_t &rhs) const noexcept {
324+
constexpr auto operator<=>(const hobject_t &rhs) const noexcept {
322325
auto cmp = max <=> rhs.max;
323326
if (cmp != 0) return cmp;
324327
cmp = pool <=> rhs.pool;
@@ -335,10 +338,11 @@ struct hobject_t {
335338
if (cmp != 0) return cmp;
336339
return snap <=> rhs.snap;
337340
}
338-
bool operator==(const hobject_t& rhs) const noexcept {
341+
constexpr bool operator==(const hobject_t& rhs) const noexcept {
339342
return operator<=>(rhs) == 0;
340343
}
341344
friend struct ghobject_t;
345+
friend struct test_hobject_fmt_t;
342346
};
343347
WRITE_CLASS_ENCODER(hobject_t)
344348

@@ -351,6 +355,54 @@ template<> struct hash<hobject_t> {
351355
};
352356
} // namespace std
353357

358+
namespace fmt {
359+
template <>
360+
struct formatter<hobject_t> {
361+
362+
template <typename FormatContext>
363+
static inline auto
364+
append_sanitized(FormatContext& ctx, const std::string& in, int sep = 0)
365+
{
366+
for (const auto i : in) {
367+
if (i == '%' || i == ':' || i == '/' || i < 32 || i >= 127) {
368+
fmt::format_to(
369+
ctx.out(), FMT_COMPILE("%{:02x}"), static_cast<unsigned char>(i));
370+
} else {
371+
fmt::format_to(ctx.out(), FMT_COMPILE("{:c}"), i);
372+
}
373+
}
374+
if (sep) {
375+
fmt::format_to(
376+
ctx.out(), FMT_COMPILE("{:c}"), sep);
377+
}
378+
return ctx.out();
379+
}
380+
381+
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
382+
383+
template <typename FormatContext>
384+
auto format(const hobject_t& ho, FormatContext& ctx)
385+
{
386+
if (ho == hobject_t{}) {
387+
return fmt::format_to(ctx.out(), "MIN");
388+
}
389+
390+
if (ho.is_max()) {
391+
return fmt::format_to(ctx.out(), "MAX");
392+
}
393+
394+
fmt::format_to(
395+
ctx.out(), FMT_COMPILE("{}:{:08x}:"), static_cast<uint64_t>(ho.pool),
396+
ho.get_bitwise_key_u32());
397+
append_sanitized(ctx, ho.nspace, ':');
398+
append_sanitized(ctx, ho.get_key(), ':');
399+
append_sanitized(ctx, ho.oid.name);
400+
return fmt::format_to(ctx.out(), FMT_COMPILE(":{}"), ho.snap);
401+
}
402+
};
403+
} // namespace fmt
404+
405+
354406
std::ostream& operator<<(std::ostream& out, const hobject_t& o);
355407

356408
template <typename T>
@@ -495,7 +547,7 @@ struct ghobject_t {
495547
void dump(ceph::Formatter *f) const;
496548
static void generate_test_instances(std::list<ghobject_t*>& o);
497549
friend int cmp(const ghobject_t& l, const ghobject_t& r);
498-
auto operator<=>(const ghobject_t&) const = default;
550+
constexpr auto operator<=>(const ghobject_t&) const = default;
499551
bool operator==(const ghobject_t&) const = default;
500552
};
501553
WRITE_CLASS_ENCODER(ghobject_t)

src/common/hobject_fmt.h

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/crimson/osd/backfill_state.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <algorithm>
55
#include <boost/type_index.hpp>
66
#include <fmt/ranges.h>
7-
#include "common/hobject_fmt.h"
7+
#include "common/hobject.h"
88
#include "crimson/osd/backfill_state.h"
99
#include "osd/osd_types_fmt.h"
1010

src/crimson/osd/pg.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <fmt/format.h>
1515
#include <fmt/ostream.h>
1616

17-
#include "common/hobject_fmt.h"
17+
#include "common/hobject.h"
1818

1919
#include "messages/MOSDOp.h"
2020
#include "messages/MOSDOpReply.h"

src/crimson/osd/scrub/scrub_machine.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
#include "common/fmt_common.h"
2020
#include "common/hobject.h"
21-
#include "common/hobject_fmt.h"
2221
#include "crimson/common/log.h"
2322
#include "osd/osd_types_fmt.h"
2423
#include "scrub_validator.h"

src/include/object.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include <string>
2424
#include <string_view>
2525

26+
#include <fmt/compile.h>
27+
#include <fmt/format.h>
28+
2629
#include "include/rados.h"
2730
#include "include/unordered_map.h"
2831
#include "common/Formatter.h"
@@ -112,10 +115,10 @@ struct file_object_t {
112115
struct snapid_t {
113116
uint64_t val;
114117
// cppcheck-suppress noExplicitConstructor
115-
snapid_t(uint64_t v=0) : val(v) {}
118+
constexpr snapid_t(uint64_t v=0) : val(v) {}
116119
snapid_t operator+=(snapid_t o) { val += o.val; return *this; }
117120
snapid_t operator++() { ++val; return *this; }
118-
operator uint64_t() const { return val; }
121+
constexpr operator uint64_t() const { return val; }
119122
};
120123

121124
inline void encode(snapid_t i, ceph::buffer::list &bl) {
@@ -153,6 +156,25 @@ inline std::ostream& operator<<(std::ostream& out, const snapid_t& s) {
153156
return out << std::hex << s.val << std::dec;
154157
}
155158

159+
namespace fmt {
160+
template <>
161+
struct formatter<snapid_t> {
162+
163+
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
164+
165+
template <typename FormatContext>
166+
auto format(const snapid_t& snp, FormatContext& ctx) const
167+
{
168+
if (snp == CEPH_NOSNAP) {
169+
return fmt::format_to(ctx.out(), "head");
170+
}
171+
if (snp == CEPH_SNAPDIR) {
172+
return fmt::format_to(ctx.out(), "snapdir");
173+
}
174+
return fmt::format_to(ctx.out(), FMT_COMPILE("{:x}"), snp.val);
175+
}
176+
};
177+
} // namespace fmt
156178

157179
struct sobject_t {
158180
object_t oid;

src/include/object_fmt.h

Lines changed: 0 additions & 29 deletions
This file was deleted.

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)