Commit a6e2f237 authored by gabime's avatar gabime

Pattern formatter optimizations

parent 87e01353
...@@ -26,17 +26,13 @@ inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest) ...@@ -26,17 +26,13 @@ inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest)
dest.append(buf_ptr, buf_ptr + buf.size()); dest.append(buf_ptr, buf_ptr + buf.size());
} }
inline void append_int(int n, fmt::memory_buffer &dest) template<typename T>
inline void append_int(T n, fmt::memory_buffer &dest)
{ {
fmt::format_int i(n); fmt::format_int i(n);
dest.append(i.data(), i.data() + i.size()); dest.append(i.data(), i.data() + i.size());
} }
inline void append_size_t(size_t n, fmt::memory_buffer &dest)
{
fmt::format_int i(n);
dest.append(i.data(), i.data() + i.size());
}
inline void append_and_pad2(int n, fmt::memory_buffer &dest) inline void append_and_pad2(int n, fmt::memory_buffer &dest)
{ {
...@@ -64,12 +60,17 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest) ...@@ -64,12 +60,17 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest)
} }
if (n > 9) // 10-99 if (n > 9) // 10-99
{ {
dest.push_back('0'); dest.push_back('0');
dest.push_back('0' + n / 10);
dest.push_back('0' + n % 10);
return;
} }
else if (n >= 0) else if (n >= 0)
{ {
dest.push_back('0'); dest.push_back('0');
dest.push_back('0'); dest.push_back('0');
dest.push_back('0' + n);
return;
} }
// negatives (unlikely, but just in case let fmt deal with it) // negatives (unlikely, but just in case let fmt deal with it)
else else
...@@ -77,7 +78,7 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest) ...@@ -77,7 +78,7 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest)
fmt::format_to(dest, "{:03}", n); fmt::format_to(dest, "{:03}", n);
return; return;
} }
append_int(n, dest);
} }
inline void append_and_pad6(int n, fmt::memory_buffer &dest) inline void append_and_pad6(int n, fmt::memory_buffer &dest)
......
...@@ -460,13 +460,12 @@ class full_formatter SPDLOG_FINAL : public flag_formatter ...@@ -460,13 +460,12 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override
{ {
#ifndef SPDLOG_NO_DATETIME #ifndef SPDLOG_NO_DATETIME
auto duration = msg.time.time_since_epoch();
// each second cache the header // each second cache the header
auto duration = msg.time.time_since_epoch();
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds) if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
{ {
cached_header_ = std::move(fmt::memory_buffer()); cached_header_ = std::move(fmt::memory_buffer());
cached_header_.push_back('['); cached_header_.push_back('[');
fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_); fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_);
...@@ -491,19 +490,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter ...@@ -491,19 +490,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
} }
fmt_helper::append_buf(cached_header_, dest); fmt_helper::append_buf(cached_header_, dest);
//
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
fmt_helper::append_and_pad3(static_cast<int>(millis), dest);
if (cached_millis_.size() == 0 || millis != cached_millis_ts_) dest.push_back(']');
{ dest.push_back(' ');
cached_millis_ = std::move(fmt::memory_buffer());
fmt_helper::append_and_pad3(static_cast<int>(millis), cached_millis_);
cached_millis_.push_back(']');
cached_millis_.push_back(' ');
cached_millis_ts_ = millis;
}
fmt_helper::append_buf(cached_millis_, dest);
#else // no datetime needed #else // no datetime needed
(void)tm_time; (void)tm_time;
#endif #endif
...@@ -528,226 +518,237 @@ class full_formatter SPDLOG_FINAL : public flag_formatter ...@@ -528,226 +518,237 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
private: private:
std::chrono::seconds::rep cached_seconds_ts_{0}; std::chrono::seconds::rep cached_seconds_ts_{0};
std::chrono::milliseconds::rep cached_millis_ts_{0};
fmt::memory_buffer cached_header_; fmt::memory_buffer cached_header_;
fmt::memory_buffer cached_millis_;
}; };
} // namespace details } // namespace details
} // namespace spdlog
///////////////////////////////////////////////////////////////////////////////
// pattern_formatter inline impl
///////////////////////////////////////////////////////////////////////////////
inline spdlog::pattern_formatter::pattern_formatter(const std::string &pattern, pattern_time_type pattern_time, std::string eol)
: eol_(std::move(eol))
, pattern_time_(pattern_time)
{
compile_pattern(pattern);
}
inline void spdlog::pattern_formatter::compile_pattern(const std::string &pattern) class pattern_formatter SPDLOG_FINAL : public formatter
{ {
auto end = pattern.end(); public:
std::unique_ptr<details::aggregate_formatter> user_chars; explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
for (auto it = pattern.begin(); it != end; ++it) std::string eol = spdlog::details::os::default_eol)
: eol_(std::move(eol))
, pattern_time_(pattern_time)
{ {
if (*it == '%') compile_pattern(pattern);
}
pattern_formatter(const pattern_formatter &) = default;
pattern_formatter &operator=(const pattern_formatter &) = default;
void format(const details::log_msg &msg, fmt::memory_buffer &dest) override
{
#ifndef SPDLOG_NO_DATETIME
auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());
if (secs != last_log_secs_)
{ {
if (user_chars) // append user chars found so far cached_tm_ = get_time(msg);
{ last_log_secs_ = secs;
formatters_.push_back(std::move(user_chars));
}
// if(
if (++it != end)
{
handle_flag(*it);
}
else
{
break;
}
} }
else // chars not following the % sign should be displayed as is #endif
for (auto &f : formatters_)
{ {
if (!user_chars) f->format(msg, cached_tm_, dest);
{
user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
}
user_chars->add_ch(*it);
} }
// write eol
details::fmt_helper::append_str(eol_, dest);
} }
if (user_chars) // append raw chars found so far
{
formatters_.push_back(std::move(user_chars));
}
}
inline void spdlog::pattern_formatter::handle_flag(char flag)
{
switch (flag)
{
// logger name
case 'n':
formatters_.emplace_back(new details::name_formatter());
break;
case 'l':
formatters_.emplace_back(new details::level_formatter());
break;
case 'L':
formatters_.emplace_back(new details::short_level_formatter());
break;
case ('t'):
formatters_.emplace_back(new details::t_formatter());
break;
case ('v'):
formatters_.emplace_back(new details::v_formatter());
break;
case ('a'):
formatters_.emplace_back(new details::a_formatter());
break;
case ('A'):
formatters_.emplace_back(new details::A_formatter());
break;
case ('b'):
case ('h'):
formatters_.emplace_back(new details::b_formatter());
break;
case ('B'):
formatters_.emplace_back(new details::B_formatter());
break;
case ('c'):
formatters_.emplace_back(new details::c_formatter());
break;
case ('C'):
formatters_.emplace_back(new details::C_formatter());
break;
case ('Y'):
formatters_.emplace_back(new details::Y_formatter());
break;
case ('D'):
case ('x'):
formatters_.emplace_back(new details::D_formatter());
break;
case ('m'):
formatters_.emplace_back(new details::m_formatter());
break;
case ('d'):
formatters_.emplace_back(new details::d_formatter());
break;
case ('H'):
formatters_.emplace_back(new details::H_formatter());
break;
case ('I'):
formatters_.emplace_back(new details::I_formatter());
break;
case ('M'):
formatters_.emplace_back(new details::M_formatter());
break;
case ('S'):
formatters_.emplace_back(new details::S_formatter());
break;
case ('e'):
formatters_.emplace_back(new details::e_formatter());
break;
case ('f'):
formatters_.emplace_back(new details::f_formatter());
break;
case ('F'):
formatters_.emplace_back(new details::F_formatter());
break;
case ('E'):
formatters_.emplace_back(new details::E_formatter());
break;
case ('p'):
formatters_.emplace_back(new details::p_formatter());
break;
case ('r'): private:
formatters_.emplace_back(new details::r_formatter()); const std::string eol_;
break; const pattern_time_type pattern_time_;
std::tm cached_tm_{};
case ('R'): std::chrono::seconds last_log_secs_;
formatters_.emplace_back(new details::R_formatter());
break;
case ('T'):
case ('X'):
formatters_.emplace_back(new details::T_formatter());
break;
case ('z'):
formatters_.emplace_back(new details::z_formatter());
break;
case ('+'):
formatters_.emplace_back(new details::full_formatter());
break;
case ('P'):
formatters_.emplace_back(new details::pid_formatter());
break;
case ('i'):
formatters_.emplace_back(new details::i_formatter());
break;
case ('^'):
formatters_.emplace_back(new details::color_start_formatter());
break;
case ('$'):
formatters_.emplace_back(new details::color_stop_formatter());
break;
default: // Unknown flag appears as is
formatters_.emplace_back(new details::ch_formatter('%'));
formatters_.emplace_back(new details::ch_formatter(flag));
break;
}
}
inline std::tm spdlog::pattern_formatter::get_time(const details::log_msg &msg) std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
{ std::tm get_time(const details::log_msg &msg)
if (pattern_time_ == pattern_time_type::local) {
if (pattern_time_ == pattern_time_type::local)
{
return details::os::localtime(log_clock::to_time_t(msg.time));
}
return details::os::gmtime(log_clock::to_time_t(msg.time));
}
void handle_flag(char flag)
{ {
return details::os::localtime(log_clock::to_time_t(msg.time)); switch (flag)
{
// logger name
case 'n':
formatters_.emplace_back(new details::name_formatter());
break;
case 'l':
formatters_.emplace_back(new details::level_formatter());
break;
case 'L':
formatters_.emplace_back(new details::short_level_formatter());
break;
case ('t'):
formatters_.emplace_back(new details::t_formatter());
break;
case ('v'):
formatters_.emplace_back(new details::v_formatter());
break;
case ('a'):
formatters_.emplace_back(new details::a_formatter());
break;
case ('A'):
formatters_.emplace_back(new details::A_formatter());
break;
case ('b'):
case ('h'):
formatters_.emplace_back(new details::b_formatter());
break;
case ('B'):
formatters_.emplace_back(new details::B_formatter());
break;
case ('c'):
formatters_.emplace_back(new details::c_formatter());
break;
case ('C'):
formatters_.emplace_back(new details::C_formatter());
break;
case ('Y'):
formatters_.emplace_back(new details::Y_formatter());
break;
case ('D'):
case ('x'):
formatters_.emplace_back(new details::D_formatter());
break;
case ('m'):
formatters_.emplace_back(new details::m_formatter());
break;
case ('d'):
formatters_.emplace_back(new details::d_formatter());
break;
case ('H'):
formatters_.emplace_back(new details::H_formatter());
break;
case ('I'):
formatters_.emplace_back(new details::I_formatter());
break;
case ('M'):
formatters_.emplace_back(new details::M_formatter());
break;
case ('S'):
formatters_.emplace_back(new details::S_formatter());
break;
case ('e'):
formatters_.emplace_back(new details::e_formatter());
break;
case ('f'):
formatters_.emplace_back(new details::f_formatter());
break;
case ('F'):
formatters_.emplace_back(new details::F_formatter());
break;
case ('E'):
formatters_.emplace_back(new details::E_formatter());
break;
case ('p'):
formatters_.emplace_back(new details::p_formatter());
break;
case ('r'):
formatters_.emplace_back(new details::r_formatter());
break;
case ('R'):
formatters_.emplace_back(new details::R_formatter());
break;
case ('T'):
case ('X'):
formatters_.emplace_back(new details::T_formatter());
break;
case ('z'):
formatters_.emplace_back(new details::z_formatter());
break;
case ('+'):
formatters_.emplace_back(new details::full_formatter());
break;
case ('P'):
formatters_.emplace_back(new details::pid_formatter());
break;
case ('i'):
formatters_.emplace_back(new details::i_formatter());
break;
case ('^'):
formatters_.emplace_back(new details::color_start_formatter());
break;
case ('$'):
formatters_.emplace_back(new details::color_stop_formatter());
break;
default: // Unknown flag appears as is
formatters_.emplace_back(new details::ch_formatter('%'));
formatters_.emplace_back(new details::ch_formatter(flag));
break;
}
} }
return details::os::gmtime(log_clock::to_time_t(msg.time));
}
inline void spdlog::pattern_formatter::format(const details::log_msg &msg, fmt::memory_buffer &dest)
{
#ifndef SPDLOG_NO_DATETIME void compile_pattern(const std::string &pattern)
auto tm_time = get_time(msg);
#else
std::tm tm_time;
#endif
for (auto &f : formatters_)
{ {
f->format(msg, tm_time, dest); auto end = pattern.end();
std::unique_ptr<details::aggregate_formatter> user_chars;
for (auto it = pattern.begin(); it != end; ++it)
{
if (*it == '%')
{
if (user_chars) // append user chars found so far
{
formatters_.push_back(std::move(user_chars));
}
// if(
if (++it != end)
{
handle_flag(*it);
}
else
{
break;
}
}
else // chars not following the % sign should be displayed as is
{
if (!user_chars)
{
user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
}
user_chars->add_ch(*it);
}
}
if (user_chars) // append raw chars found so far
{
formatters_.push_back(std::move(user_chars));
}
} }
// write eol };
details::fmt_helper::append_str(eol_, dest); } // namespace spdlog
}
...@@ -20,28 +20,6 @@ public: ...@@ -20,28 +20,6 @@ public:
virtual ~formatter() = default; virtual ~formatter() = default;
virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0; virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0;
}; };
namespace details {
class flag_formatter;
}
class pattern_formatter SPDLOG_FINAL : public formatter
{
public:
explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
std::string eol = spdlog::details::os::default_eol);
pattern_formatter(const pattern_formatter &) = default;
pattern_formatter &operator=(const pattern_formatter &) = default;
void format(const details::log_msg &msg, fmt::memory_buffer &dest) override;
private:
const std::string eol_;
const pattern_time_type pattern_time_;
std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
std::tm get_time(const details::log_msg &msg);
void handle_flag(char flag);
void compile_pattern(const std::string &pattern);
};
} // namespace spdlog } // namespace spdlog
#include "details/pattern_formatter_impl.h" #include "details/pattern_formatter_impl.h"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment