From 8a29878d94e08159bd2e72b4e23b76494c42d338 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 7 Mar 2023 21:34:40 +0800 Subject: [PATCH 1/3] add async write mode --- include/easylog/easylog.h | 42 ++++++++++++++++++++++++---- include/easylog/record.hpp | 13 +++++---- src/easylog/benchmark/CMakeLists.txt | 4 +++ src/easylog/benchmark/main.cpp | 31 ++++++++++++-------- src/easylog/tests/CMakeLists.txt | 7 +++-- 5 files changed, 73 insertions(+), 24 deletions(-) diff --git a/include/easylog/easylog.h b/include/easylog/easylog.h index af96e27b2..765405fda 100644 --- a/include/easylog/easylog.h +++ b/include/easylog/easylog.h @@ -14,6 +14,8 @@ * limitations under the License. */ #pragma once +#include +#include #include #include #include @@ -31,7 +33,16 @@ class logger { return instance; } - void operator+=(const record_t &record) { write(record); } + void operator+=(record_t &&record) { + if (async_mode_) { + asio::post(pool_, [this, record = std::move(record)]() mutable { + write(record); + }); + } + else { + write(record); + } + } void write(const record_t &record) { append_format(record); @@ -64,6 +75,13 @@ class logger { appenders_.emplace_back(std::move(fn)); } + void drain() { + if (async_mode_) { + pool_.wait(); + } + } + void enable_async() { async_mode_ = true; } + private: logger() = default; logger(const logger &) = default; @@ -104,17 +122,17 @@ class logger { str.append(record.get_file_str()); str.append(record.get_message()).append("\n"); - if (appender_) { - appender_->write(str); - } + appender_->write(str); if (enable_console_) { std::cout << str; std::cout << std::flush; } - for (auto &fn : appenders_) { - fn(std::string_view(str)); + if (!appenders_.empty()) { + for (auto &fn : appenders_) { + fn(std::string_view(str)); + } } } @@ -122,6 +140,8 @@ class logger { bool enable_console_ = true; appender *appender_ = nullptr; std::vector> appenders_; + bool async_mode_ = false; + asio::thread_pool pool_{1}; }; template @@ -132,6 +152,16 @@ inline void init_log(Severity min_severity, const std::string &filename = "", max_file_size, max_files, flush_every_time); } +template +void drain() { + logger::instance().drain(); +} + +template +void enable_async() { + logger::instance().enable_async(); +} + template inline void flush() { logger::instance().flush(); diff --git a/include/easylog/record.hpp b/include/easylog/record.hpp index d2282a3f6..fc5b8b0f6 100644 --- a/include/easylog/record.hpp +++ b/include/easylog/record.hpp @@ -104,6 +104,9 @@ class record_t { buf_len_ = str.size(); } + record_t(const record_t &) = delete; + record_t(record_t &&) = default; + Severity get_severity() const { return severity_; } const char *get_message() const { return ss_.data(); } @@ -114,10 +117,10 @@ class record_t { auto get_time_point() const { return tm_point_; } - record_t &ref() { return *this; } + record_t &&ref() { return std::move(*this); } template - record_t &operator<<(const T &data) { + record_t &&operator<<(const T &data) { using U = std::remove_cvref_t; if constexpr (std::is_floating_point_v) { char temp[40]; @@ -140,14 +143,14 @@ class record_t { ss_.append(data); } - return *this; + return std::move(*this); } template - record_t &sprintf(const char *fmt, Args... args) { + record_t &&sprintf(const char *fmt, Args... args) { printf_string_format(fmt, args...); - return *this; + return std::move(*this); } private: diff --git a/src/easylog/benchmark/CMakeLists.txt b/src/easylog/benchmark/CMakeLists.txt index 37f09e4a3..360ec3a59 100644 --- a/src/easylog/benchmark/CMakeLists.txt +++ b/src/easylog/benchmark/CMakeLists.txt @@ -11,3 +11,7 @@ if (glog_FOUND) target_compile_definitions(easylog_benchmark PRIVATE HAVE_GLOG) target_link_libraries(easylog_benchmark PRIVATE glog::glog) endif () + +target_include_directories(easylog_benchmark PRIVATE + ${yaLanTingLibs_SOURCE_DIR}/thirdparty/asio +) diff --git a/src/easylog/benchmark/main.cpp b/src/easylog/benchmark/main.cpp index 91ee9875a..6cee53035 100644 --- a/src/easylog/benchmark/main.cpp +++ b/src/easylog/benchmark/main.cpp @@ -47,19 +47,23 @@ class ScopedTimer { uint64_t *m_ns = nullptr; }; +bool first_init = true; void test_glog() { #ifdef HAVE_GLOG std::filesystem::remove("glog.txt"); - FLAGS_log_dir = "."; - FLAGS_minloglevel = google::GLOG_INFO; - FLAGS_timestamp_in_logfile_name = false; - google::SetLogDestination(google::INFO, "glog.txt"); - google::InitGoogleLogging("glog"); + if (first_init) { + FLAGS_log_dir = "."; + FLAGS_minloglevel = google::GLOG_INFO; + FLAGS_timestamp_in_logfile_name = false; + google::SetLogDestination(google::INFO, "glog.txt"); + google::InitGoogleLogging("glog"); + first_init = false; + } { ScopedTimer timer("glog "); - for (int i = 0; i < 5000; i++) - LOG(INFO) << "Hello, it is a long string test! " << 42 << 21 << 2.5; + for (int i = 0; i < 10000; i++) + LOG(INFO) << "Hello, it is a long string test! " << 42 << 21 << 2.5 << i; } #endif } @@ -67,14 +71,19 @@ void test_glog() { void test_easylog() { std::filesystem::remove("easylog.txt"); easylog::init_log(Severity::DEBUG, "easylog.txt", false, 1024 * 1024, 1); + easylog::enable_async(); { ScopedTimer timer("easylog"); - for (int i = 0; i < 5000; i++) - ELOG(INFO) << "Hello, it is a long string test! " << 42 << 21 << 2.5; + for (int i = 0; i < 10000; i++) + ELOG(INFO) << "Hello, it is a long string test! " << 42 << 21 << 2.5 << i; + + easylog::drain(); } } int main() { - test_glog(); - test_easylog(); + for (int i = 0; i < 10; i++) { + test_glog(); + test_easylog(); + } } diff --git a/src/easylog/tests/CMakeLists.txt b/src/easylog/tests/CMakeLists.txt index 9d28fffdb..aaffcf982 100644 --- a/src/easylog/tests/CMakeLists.txt +++ b/src/easylog/tests/CMakeLists.txt @@ -7,8 +7,11 @@ add_executable(test_easylog add_test(NAME test_easylog COMMAND test_easylog) target_compile_definitions(test_easylog PRIVATE STRUCT_PACK_ENABLE_UNPORTABLE_TYPE) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog doctest) + target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog pthread doctest) else() - target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog doctest -lstdc++fs) + target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog pthread doctest -lstdc++fs) endif() +target_include_directories(test_easylog PRIVATE + ${yaLanTingLibs_SOURCE_DIR}/thirdparty/asio +) From 5f5a85cf1561f7ba017fc3970a43edf66ff44a48 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 7 Mar 2023 21:43:57 +0800 Subject: [PATCH 2/3] revert --- include/easylog/easylog.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/easylog/easylog.h b/include/easylog/easylog.h index 765405fda..0aa36f19b 100644 --- a/include/easylog/easylog.h +++ b/include/easylog/easylog.h @@ -122,7 +122,9 @@ class logger { str.append(record.get_file_str()); str.append(record.get_message()).append("\n"); - appender_->write(str); + if (appender_) { + appender_->write(str); + } if (enable_console_) { std::cout << str; From 987e48b24ca6e894c30daa678b07f3ad256a1847 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 8 Mar 2023 07:55:36 +0800 Subject: [PATCH 3/3] cmake --- src/easylog/tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/easylog/tests/CMakeLists.txt b/src/easylog/tests/CMakeLists.txt index aaffcf982..e58a3b3f7 100644 --- a/src/easylog/tests/CMakeLists.txt +++ b/src/easylog/tests/CMakeLists.txt @@ -7,9 +7,9 @@ add_executable(test_easylog add_test(NAME test_easylog COMMAND test_easylog) target_compile_definitions(test_easylog PRIVATE STRUCT_PACK_ENABLE_UNPORTABLE_TYPE) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog pthread doctest) + target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog -lpthread doctest) else() - target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog pthread doctest -lstdc++fs) + target_link_libraries(test_easylog PRIVATE yalantinglibs::easylog -lpthread doctest -lstdc++fs) endif() target_include_directories(test_easylog PRIVATE