fast_buf\!

This commit is contained in:
gabime 2014-03-20 03:47:57 +02:00
parent d0f3b05f90
commit ba2b6aea25
12 changed files with 75 additions and 55 deletions

View File

@ -15,14 +15,13 @@ using namespace std::chrono;
using namespace c11log; using namespace c11log;
using namespace utils; using namespace utils;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if(argc || argv) {}; if(argc || argv) {};
auto fsink = std::make_shared<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, 0); auto fsink = std::make_shared<sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5, 0);
//auto fsink = std::make_shared<sinks::simple_file_sink>("simplelog", "txt"); //auto fsink = std::make_shared<sinks::simple_file_sink>("simplelog", "txt");
auto null_sink = std::make_shared<sinks::null_sink>(); auto null_sink = std::make_shared<sinks::null_sink>();
@ -35,7 +34,7 @@ int main(int argc, char* argv[])
auto start = system_clock::now(); auto start = system_clock::now();
const unsigned int howmany = 3000000; const unsigned int howmany = 5000000;
for(unsigned int i = 0; i < howmany ; i++) for(unsigned int i = 0; i < howmany ; i++)
my_logger.info() << "Hello logger " << i; my_logger.info() << "Hello logger " << i;

View File

@ -6,6 +6,7 @@ namespace c11log
{ {
typedef std::chrono::system_clock log_clock; typedef std::chrono::system_clock log_clock;
typedef std::pair<const char*, std::size_t> bufpair_t;
namespace level namespace level
{ {

View File

@ -2,8 +2,7 @@
// Faster than ostringstream--returns its string by ref // Faster than ostringstream--returns its string by ref
#include<streambuf> #include "c11log/details/fast_buf.h"
#include<string>
namespace c11log namespace c11log
{ {
@ -12,7 +11,7 @@ namespace details
class str_devicebuf:public std::streambuf class str_devicebuf:public std::streambuf
{ {
public: public:
str_devicebuf() = default; str_devicebuf() = default;
~str_devicebuf() = default; ~str_devicebuf() = default;
@ -21,15 +20,21 @@ public:
str_devicebuf& operator=(const str_devicebuf&) = delete; str_devicebuf& operator=(const str_devicebuf&) = delete;
str_devicebuf& operator=(str_devicebuf&&) = delete; str_devicebuf& operator=(str_devicebuf&&) = delete;
/*
const std::string& str_ref() const const std::string& str_ref() const
{ {
return _str; return _str;
} }
*/
bufpair_t buf()
{
return _fastbuf.get();
}
void reset_str() void reset_str()
{ {
_str.clear(); //_str.clear();
_fastbuf.clear();
} }
protected: protected:
@ -38,32 +43,35 @@ protected:
return 0; return 0;
} }
// copy the give buffer into the accumulated string. // copy the give buffer into the accumulated string.
// reserve initially 128 bytes which should be enough for common log lines // reserve initially 128 bytes which should be enough for common log lines
std::streamsize xsputn(const char_type* s, std::streamsize count) override std::streamsize xsputn(const char_type* s, std::streamsize count) override
{ {
if(_str.capacity() < k_initial_reserve) /*
{ if(_str.capacity() < k_initial_reserve)
_str.reserve(k_initial_reserve); {
} _str.reserve(k_initial_reserve);
_str.append(s, static_cast<unsigned int>(count)); }
_str.append(s, static_cast<unsigned int>(count));
*/
_fastbuf.append(s, static_cast<unsigned int>(count));
return count; return count;
} }
int_type overflow(int_type ch) override int_type overflow(int_type ch) override
{ {
bool not_eofile = traits_type::not_eof(ch); bool not_eofile = traits_type::not_eof(ch);
if (not_eofile) if (not_eofile)
{ {
char c = traits_type::to_char_type(ch); char c = traits_type::to_char_type(ch);
xsputn(&c, 1); xsputn(&c, 1);
} }
return not_eofile; return not_eofile;
} }
private: private:
std::string _str; //std::string _str;
static constexpr std::streamsize k_initial_reserve = 128; fast_buf<128> _fastbuf;
}; };
class fast_oss:public std::ostream class fast_oss:public std::ostream
@ -75,15 +83,21 @@ public:
fast_oss(const fast_oss& other) = delete; fast_oss(const fast_oss& other) = delete;
fast_oss(fast_oss&& other) = delete; fast_oss(fast_oss&& other) = delete;
fast_oss& operator=(const fast_oss& other) = delete; fast_oss& operator=(const fast_oss& other) = delete;
/*
const std::string& str_ref() const const std::string& str_ref() const
{ {
return _dev.str_ref(); return _dev.str_ref();
} }
void reset_str() */
{ bufpair_t buf()
_dev.reset_str(); {
} return _dev.buf();
}
void reset_str()
{
_dev.reset_str();
}
private: private:
str_devicebuf _dev; str_devicebuf _dev;

View File

@ -13,9 +13,9 @@ public:
_flush_every(flush_every), _flush_every(flush_every),
_write_counter(0) {}; _write_counter(0) {};
void write(std::ofstream& ofs, const std::string& msg) void write(std::ofstream& ofs, const bufpair_t& msg)
{ {
ofs.write(msg.c_str(), msg.size()); ofs.write(msg.first, msg.second);
if(++_write_counter == _flush_every) if(++_write_counter == _flush_every)
{ {
ofs.flush(); ofs.flush();

View File

@ -50,7 +50,7 @@ public:
if (_enabled) if (_enabled)
{ {
_oss << os::eol(); _oss << os::eol();
_callback_logger->_log_it(_oss.str_ref(), _level); _callback_logger->_log_it(_oss.buf(), _level);
} }
} }

View File

@ -50,9 +50,9 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
constexpr inline const char* eol() constexpr inline const char* eol()
{ {
#ifdef _WIN32 #ifdef _WIN32
return "\r\n"; return "\r\n";
#else #else
return "\n"; return "\n";
#endif #endif
} }
} //os } //os

View File

@ -88,9 +88,10 @@ inline void c11log::formatters::default_formatter::_format_time(const log_clock:
time_oss << tm_now.tm_sec << ']'; time_oss << tm_now.tm_sec << ']';
//Cache the resulted string and its size //Cache the resulted string and its size
s_cache_time_t = tp_time_t; s_cache_time_t = tp_time_t;
const std::string &s = time_oss.str_ref(); //const std::string &s = time_oss.str_ref();
std::memcpy(s_cache_str, s.c_str(), s.size()); bufpair_t buf = time_oss.buf();
s_cache_size = s.size(); std::memcpy(s_cache_str, buf.first, buf.second);
s_cache_size = buf.second;
} }
dest.write(s_cache_str, s_cache_size); dest.write(s_cache_str, s_cache_size);
} }

View File

@ -21,6 +21,7 @@ namespace c11log
namespace details namespace details
{ {
class line_logger; class line_logger;
template<std::size_t> class fast_buf;
} }
@ -67,7 +68,7 @@ private:
sinks_vector_t _sinks; sinks_vector_t _sinks;
std::atomic_int _atomic_level; std::atomic_int _atomic_level;
void _log_it(const std::string& msg, const level::level_enum level); void _log_it(const bufpair_t& buf, const level::level_enum level);
}; };
@ -80,6 +81,7 @@ logger& get_logger(const std::string& name);
// Logger inline implementation // Logger inline implementation
// //
#include "details/line_logger.h" #include "details/line_logger.h"
#include "details/fast_buf.h"
inline c11log::logger::logger(const std::string& name, formatter_ptr f, sinks_init_list sinks_list) : inline c11log::logger::logger(const std::string& name, formatter_ptr f, sinks_init_list sinks_list) :
@ -145,10 +147,11 @@ inline bool c11log::logger::should_log(c11log::level::level_enum level) const
{ {
return level >= _atomic_level.load(); return level >= _atomic_level.load();
} }
inline void c11log::logger::_log_it(const std::string& msg, const level::level_enum level)
inline void c11log::logger::_log_it(const bufpair_t& buf, const level::level_enum level)
{ {
for (auto &sink : _sinks) for (auto &sink : _sinks)
sink->log(msg, level); sink->log(buf, level);
} }
// Static factory function // Static factory function

View File

@ -28,7 +28,7 @@ public:
protected: protected:
void _sink_it(const std::string& msg) override; void _sink_it(const bufpair_t& msg) override;
void _thread_loop(); void _thread_loop();
private: private:
@ -57,9 +57,10 @@ inline c11log::sinks::async_sink::~async_sink()
{ {
_shutdown(); _shutdown();
} }
inline void c11log::sinks::async_sink::_sink_it(const std::string& msg) inline void c11log::sinks::async_sink::_sink_it(const bufpair_t& msg)
{ {
_q.push(msg); std::string s {msg.first, msg.first+msg.second};
_q.push(s);
} }
inline void c11log::sinks::async_sink::_thread_loop() inline void c11log::sinks::async_sink::_thread_loop()
@ -71,9 +72,10 @@ inline void c11log::sinks::async_sink::_thread_loop()
{ {
if (_q.pop(msg, pop_timeout)) if (_q.pop(msg, pop_timeout))
{ {
bufpair_t buf(msg.data(), msg.size());
for (auto &sink : _sinks) for (auto &sink : _sinks)
{ {
sink->log(msg, static_cast<level::level_enum>(_level.load())); sink->log(buf, static_cast<level::level_enum>(_level.load()));
if (!_active) if (!_active)
return; return;
} }

View File

@ -22,7 +22,7 @@ public:
base_sink(const base_sink&) = delete; base_sink(const base_sink&) = delete;
base_sink& operator=(const base_sink&) = delete; base_sink& operator=(const base_sink&) = delete;
void log(const std::string &msg, level::level_enum level) void log(const bufpair_t &msg, level::level_enum level)
{ {
if (level >= _level) if (level >= _level)
{ {
@ -36,14 +36,14 @@ public:
} }
protected: protected:
virtual void _sink_it(const std::string& msg) = 0; virtual void _sink_it(const bufpair_t& msg) = 0;
std::atomic<int> _level {level::INFO}; std::atomic<int> _level {level::INFO};
}; };
class null_sink:public base_sink class null_sink:public base_sink
{ {
protected: protected:
void _sink_it(const std::string& ) override void _sink_it(const bufpair_t& ) override
{ {
} }
}; };

View File

@ -19,10 +19,10 @@ public:
virtual ~console_sink() = default; virtual ~console_sink() = default;
protected: protected:
virtual void _sink_it(const std::string& msg) override virtual void _sink_it(const bufpair_t& msg) override
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_ostream << msg; _ostream.write(msg.first, msg.second);
} }
std::ostream& _ostream; std::ostream& _ostream;

View File

@ -26,7 +26,7 @@ public:
{ {
} }
protected: protected:
void _sink_it(const std::string& msg) override void _sink_it(const bufpair_t& msg) override
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_flush_helper.write(_ofstream, msg); _flush_helper.write(_ofstream, msg);
@ -59,14 +59,14 @@ public:
} }
protected: protected:
void _sink_it(const std::string& msg) override void _sink_it(const bufpair_t& msg) override
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_current_size += msg.length(); _current_size += msg.second;
if (_current_size > _max_size) if (_current_size > _max_size)
{ {
_rotate(); _rotate();
_current_size = msg.length(); _current_size = msg.second;
} }
_flush_helper.write(_ofstream, msg); _flush_helper.write(_ofstream, msg);
} }
@ -132,7 +132,7 @@ public:
} }
protected: protected:
void _sink_it(const std::string& msg) override void _sink_it(const bufpair_t& msg) override
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
if (std::chrono::system_clock::now() >= _midnight_tp) if (std::chrono::system_clock::now() >= _midnight_tp)