From: Ronen Friedman Date: Sun, 18 Feb 2024 06:32:10 +0000 (-0600) Subject: common: improve hobject_t fmtlib formatter performance X-Git-Tag: testing/wip-batrick-testing-20240411.154038~384^2~4 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=ec1cd79b37153dd23391c742536d64df1ba8c52d;p=ceph-ci.git common: improve hobject_t fmtlib formatter performance The new version of the code only takes about 38% of the time of the old one. See https://github.com/ronen-fr/hobjtostr/tree/rf-2 for the code used to benchmark the new version. hobject_fmt.h is folded into hobject.h, as fmtlib is now an accepted dependency in all of Ceph. Signed-off-by: Ronen Friedman --- diff --git a/src/common/hobject.h b/src/common/hobject.h index fe7f9a705c9..d8754550a0d 100644 --- a/src/common/hobject.h +++ b/src/common/hobject.h @@ -15,6 +15,9 @@ #ifndef __CEPH_OS_HOBJECT_H #define __CEPH_OS_HOBJECT_H +#include +#include + #if FMT_VERSION >= 90000 #include #endif @@ -351,6 +354,54 @@ template<> struct hash { }; } // namespace std +namespace fmt { +template <> +struct formatter { + + template + static inline auto + append_sanitized(FormatContext& ctx, const std::string& in, int sep = 0) + { + for (const auto i : in) { + if (i == '%' || i == ':' || i == '/' || i < 32 || i >= 127) { + fmt::format_to( + ctx.out(), FMT_COMPILE("%{:02x}"), static_cast(i)); + } else { + fmt::format_to(ctx.out(), FMT_COMPILE("{:c}"), i); + } + } + if (sep) { + fmt::format_to( + ctx.out(), FMT_COMPILE("{:c}"), sep); + } + return ctx.out(); + } + + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + + template + auto format(const hobject_t& ho, FormatContext& ctx) + { + if (ho == hobject_t{}) { + return fmt::format_to(ctx.out(), "MIN"); + } + + if (ho.is_max()) { + return fmt::format_to(ctx.out(), "MAX"); + } + + fmt::format_to( + ctx.out(), FMT_COMPILE("{}:{:08x}:"), static_cast(ho.pool), + ho.get_bitwise_key_u32()); + append_sanitized(ctx, ho.nspace, ':'); + append_sanitized(ctx, ho.get_key(), ':'); + append_sanitized(ctx, ho.oid.name); + return fmt::format_to(ctx.out(), FMT_COMPILE(":{}"), ho.snap); + } +}; +} // namespace fmt + + std::ostream& operator<<(std::ostream& out, const hobject_t& o); template diff --git a/src/common/hobject_fmt.h b/src/common/hobject_fmt.h deleted file mode 100644 index a2a730e1c5f..00000000000 --- a/src/common/hobject_fmt.h +++ /dev/null @@ -1,52 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -#pragma once - -/** - * \file fmtlib formatters for some hobject.h classes - */ -#include -#include - -#include "common/hobject.h" -#include "msg/msg_fmt.h" - -// \todo reimplement -static inline void append_out_escaped(const std::string& in, std::string* out) -{ - for (auto i = in.cbegin(); i != in.cend(); ++i) { - if (*i == '%' || *i == ':' || *i == '/' || *i < 32 || *i >= 127) { - char buf[4]; - snprintf(buf, sizeof(buf), "%%%02x", (int)(unsigned char)*i); - out->append(buf); - } else { - out->push_back(*i); - } - } -} - -template <> struct fmt::formatter { - - constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } - - template auto format(const hobject_t& ho, FormatContext& ctx) - { - if (ho == hobject_t{}) { - return fmt::format_to(ctx.out(), "MIN"); - } - - if (ho.is_max()) { - return fmt::format_to(ctx.out(), "MAX"); - } - - std::string v; - append_out_escaped(ho.nspace, &v); - v.push_back(':'); - append_out_escaped(ho.get_key(), &v); - v.push_back(':'); - append_out_escaped(ho.oid.name, &v); - - return fmt::format_to(ctx.out(), "{}:{:08x}:{}:{}", static_cast(ho.pool), - ho.get_bitwise_key_u32(), v, ho.snap); - } -}; diff --git a/src/crimson/osd/backfill_state.cc b/src/crimson/osd/backfill_state.cc index 46a270ffe54..92b3ea8714c 100644 --- a/src/crimson/osd/backfill_state.cc +++ b/src/crimson/osd/backfill_state.cc @@ -4,7 +4,7 @@ #include #include #include -#include "common/hobject_fmt.h" +#include "common/hobject.h" #include "crimson/osd/backfill_state.h" #include "osd/osd_types_fmt.h" diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index 54c8101cd11..697f4e2225c 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -14,7 +14,7 @@ #include #include -#include "common/hobject_fmt.h" +#include "common/hobject.h" #include "messages/MOSDOp.h" #include "messages/MOSDOpReply.h" diff --git a/src/crimson/osd/scrub/scrub_machine.h b/src/crimson/osd/scrub/scrub_machine.h index d2d127adc0d..f6cec5cba71 100644 --- a/src/crimson/osd/scrub/scrub_machine.h +++ b/src/crimson/osd/scrub/scrub_machine.h @@ -18,7 +18,6 @@ #include "common/fmt_common.h" #include "common/hobject.h" -#include "common/hobject_fmt.h" #include "crimson/common/log.h" #include "osd/osd_types_fmt.h" #include "scrub_validator.h" diff --git a/src/msg/msg_types.h b/src/msg/msg_types.h index b39120cc08d..e1e3ecca749 100644 --- a/src/msg/msg_types.h +++ b/src/msg/msg_types.h @@ -98,6 +98,15 @@ public: } void dump(ceph::Formatter *f) const; + template + auto fmt_print_ctx(FormatContext& ctx) const { + if (is_new() || _num < 0) { + return fmt::format_to(ctx.out(), "{}.?", type_str()); + } else { + return fmt::format_to(ctx.out(), "{}.{}",type_str(), _num); + } + } + static void generate_test_instances(std::list& o); }; WRITE_CLASS_DENC(entity_name_t) diff --git a/src/osd/osd_types_fmt.h b/src/osd/osd_types_fmt.h index e467d5d2304..a88bf08c5ec 100644 --- a/src/osd/osd_types_fmt.h +++ b/src/osd/osd_types_fmt.h @@ -5,9 +5,10 @@ * \file fmtlib formatters for some types.h classes */ -#include "common/hobject_fmt.h" +#include "common/hobject.h" #include "osd/osd_types.h" #include +#include #if FMT_VERSION >= 90000 #include #endif