From 9f51c017e7302ffd28261f833b4be3c35fcf6eb7 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Tue, 6 Dec 2022 23:14:23 +0800 Subject: [PATCH] upd: [imp] optimize the size of the fmt context --- include/libimp/fmt_cpo.h | 5 ---- src/libimp/fmt.cpp | 58 +++++++++++++++++++++++++-------------- test/imp/test_imp_fmt.cpp | 17 +++++------- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/include/libimp/fmt_cpo.h b/include/libimp/fmt_cpo.h index 3d94ec5..dbb28bd 100644 --- a/include/libimp/fmt_cpo.h +++ b/include/libimp/fmt_cpo.h @@ -7,7 +7,6 @@ #pragma once #include -#include #include #include "libimp/def.h" @@ -18,14 +17,10 @@ LIBIMP_NAMESPACE_BEG_ -constexpr std::size_t fmt_context_aligned_size = 512U; - /** * @brief The context of fmt. */ class LIBIMP_EXPORT fmt_context { - std::array sbuf_; - std::string &joined_; std::size_t offset_; diff --git a/src/libimp/fmt.cpp b/src/libimp/fmt.cpp index dfeb228..39c34f2 100644 --- a/src/libimp/fmt.cpp +++ b/src/libimp/fmt.cpp @@ -19,8 +19,18 @@ LIBIMP_NAMESPACE_BEG_ */ namespace { -constexpr std::size_t roundup(std::size_t sz) noexcept { - return (sz & ~(fmt_context_aligned_size - 1)) + fmt_context_aligned_size; +struct sfmt_policy { + constexpr static std::size_t aligned_size = 32U; +}; + +struct sbuf_policy { + constexpr static std::size_t aligned_size = 2048U; +}; + +template +span local_fmt_sbuf() noexcept { + thread_local std::array sbuf; + return sbuf; } span normalize(span const &a) { @@ -52,19 +62,14 @@ span sbuf_cat(span const &sbuf, std::initializer_list local_fmt_str() noexcept { - thread_local std::array sbuf; - return sbuf; -} - char const *as_cstr(span const &a) { if (a.empty()) return ""; if (a.back() == '\0') return a.data(); - return sbuf_cpy(local_fmt_str(), a).data(); + return sbuf_cpy(local_fmt_sbuf(), a).data(); } span fmt_of(span const &fstr, span const &s) { - return sbuf_cat(local_fmt_str(), {"%", fstr, s}); + return sbuf_cat(local_fmt_sbuf(), {"%", fstr, s}); } span fmt_of_unsigned(span fstr, span const &l) { @@ -76,8 +81,8 @@ span fmt_of_unsigned(span fstr, span const &l) { case 'o': case 'x': case 'X': - case 'u': return sbuf_cat(local_fmt_str(), {"%", fstr.first(fstr.size() - 1), l, fstr.last(1)}); - default : return sbuf_cat(local_fmt_str(), {"%", fstr, l, "u"}); + case 'u': return sbuf_cat(local_fmt_sbuf(), {"%", fstr.first(fstr.size() - 1), l, fstr.last(1)}); + default : return sbuf_cat(local_fmt_sbuf(), {"%", fstr, l, "u"}); } } @@ -91,7 +96,7 @@ span fmt_of_signed(span fstr, span const &l) { case 'x': case 'X': case 'u': return fmt_of_unsigned(fstr, l); - default : return sbuf_cat(local_fmt_str(), {"%", fstr, l, "d"}); + default : return sbuf_cat(local_fmt_sbuf(), {"%", fstr, l, "d"}); } } @@ -104,8 +109,8 @@ span fmt_of_float(span fstr, span const &l) { case 'e': case 'E': case 'g': - case 'G': return sbuf_cat(local_fmt_str(), {"%", fstr.first(fstr.size() - 1), l, fstr.last(1)}); - default : return sbuf_cat(local_fmt_str(), {"%", fstr, l, "f"}); + case 'G': return sbuf_cat(local_fmt_sbuf(), {"%", fstr.first(fstr.size() - 1), l, fstr.last(1)}); + default : return sbuf_cat(local_fmt_sbuf(), {"%", fstr, l, "f"}); } } @@ -137,6 +142,10 @@ bool sprintf(fmt_context &ctx, F fop, span const &fstr, span fmt_context_sbuf() noexcept { + return local_fmt_sbuf(); +} + } // namespace /// @brief The context of fmt. @@ -146,7 +155,9 @@ fmt_context::fmt_context(std::string &j) noexcept , offset_(0) {} std::size_t fmt_context::capacity() noexcept { - return (offset_ < sbuf_.size()) ? sbuf_.size() : joined_.size(); + return (offset_ < fmt_context_sbuf().size()) + ? fmt_context_sbuf().size() + : joined_.size(); } void fmt_context::reset() noexcept { @@ -155,8 +166,8 @@ void fmt_context::reset() noexcept { bool fmt_context::finish() noexcept { LIBIMP_TRY { - if (offset_ < sbuf_.size()) { - joined_.assign(sbuf_.data(), offset_); + if (offset_ < fmt_context_sbuf().size()) { + joined_.assign(fmt_context_sbuf().data(), offset_); } else { joined_.resize(offset_); } @@ -167,13 +178,18 @@ bool fmt_context::finish() noexcept { } span fmt_context::buffer(std::size_t sz) noexcept { + auto roundup = [](std::size_t sz) noexcept { + constexpr std::size_t fmt_context_aligned_size = 512U; + return (sz & ~(fmt_context_aligned_size - 1)) + fmt_context_aligned_size; + }; + auto sbuf = fmt_context_sbuf(); LIBIMP_TRY { - if (offset_ < sbuf_.size()) { - if ((offset_ + sz) < sbuf_.size()) { - return make_span(sbuf_).subspan(offset_); + if (offset_ < sbuf.size()) { + if ((offset_ + sz) < sbuf.size()) { + return sbuf.subspan(offset_); } else { /// @remark switch the cache to std::string - joined_.assign(sbuf_.data(), offset_); + joined_.assign(sbuf.data(), offset_); joined_.resize(roundup(offset_ + sz)); } } else if ((offset_ + sz) >= joined_.size()) { diff --git a/test/imp/test_imp_fmt.cpp b/test/imp/test_imp_fmt.cpp index 3e0e39c..8836800 100644 --- a/test/imp/test_imp_fmt.cpp +++ b/test/imp/test_imp_fmt.cpp @@ -92,23 +92,20 @@ TEST(fmt, to_string) { } TEST(fmt, fmt) { + char const txt[] = "hello world."; + /// @brief hello world auto s = imp::fmt("hello", " ", "world", "."); - EXPECT_EQ(s, "hello world."); + EXPECT_EQ(s, txt); /// @brief chrono std::cout << imp::fmt('[', std::chrono::system_clock::now(), "] ", s) << "\n"; /// @brief long string - s = imp::fmt(imp::spec("1024")("hello world.")); - EXPECT_EQ(s, " " - " " - " " - " " - " " - " " - " " - " hello world."); + s = imp::fmt(imp::spec("4096")(txt)); + std::string test(4096, ' '); + std::memcpy(&test[test.size() - sizeof(txt) + 1], txt, sizeof(txt) - 1); + EXPECT_EQ(s, test); } namespace {