This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch next_stable
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


The following commit(s) were added to refs/heads/next_stable by this push:
     new de0f0b89 Reduce logging overhead by holding references (#130)
de0f0b89 is described below

commit de0f0b89e72027087f188230da8405c295263074
Author: Stephen Webb <[email protected]>
AuthorDate: Sun Sep 18 09:40:57 2022 +1000

    Reduce logging overhead by holding references (#130)
    
    * Do not copy the (const global) thread name into every LoggingEvent
    
    * Ensure thread user name is not always empty
    
    * Detect thread_local support at configure time
---
 src/cmake/test-thread-local.cpp                    | 11 ++++
 src/main/cpp/loggingevent.cpp                      | 63 ++++++++++++++++------
 src/main/include/CMakeLists.txt                    | 26 +++++++--
 .../include/log4cxx/private/log4cxx_private.h.in   | 11 +---
 src/main/include/log4cxx/spi/loggingevent.h        |  4 +-
 src/test/cpp/helpers/timezonetestcase.cpp          |  2 -
 6 files changed, 81 insertions(+), 36 deletions(-)

diff --git a/src/cmake/test-thread-local.cpp b/src/cmake/test-thread-local.cpp
new file mode 100644
index 00000000..9a8ba961
--- /dev/null
+++ b/src/cmake/test-thread-local.cpp
@@ -0,0 +1,11 @@
+#include <string>
+
+std::string& getCurrentThreadVar()
+{
+       thread_local std::string thread_id_string;
+    return thread_id_string;
+}
+
+int main(){
+       getCurrentThreadVar() = "name";
+}
diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp
index b652e7fd..8adcd0e6 100644
--- a/src/main/cpp/loggingevent.cpp
+++ b/src/main/cpp/loggingevent.cpp
@@ -51,7 +51,9 @@ struct LoggingEvent::LoggingEventPrivate
                ndcLookupRequired(true),
                mdcCopyLookupRequired(true),
                timeStamp(0),
-               locationInfo()
+               locationInfo(),
+               threadName(getCurrentThreadName()),
+               threadUserName(getCurrentThreadUserName())
        {
        }
 
@@ -68,7 +70,10 @@ struct LoggingEvent::LoggingEventPrivate
                message(message1),
                timeStamp(apr_time_now()),
                locationInfo(locationInfo1),
-               threadName(getCurrentThreadName()) {}
+               threadName(getCurrentThreadName()),
+               threadUserName(getCurrentThreadUserName())
+       {
+       }
 
        ~LoggingEventPrivate()
        {
@@ -125,14 +130,14 @@ struct LoggingEvent::LoggingEventPrivate
        /** The identifier of thread in which this logging event
        was generated.
        */
-       const LogString threadName;
+       const LogString& threadName;
 
        /**
         * The user-specified name of the thread(on a per-platform basis).
         * This is set using a method such as pthread_setname_np on POSIX
         * systems or SetThreadDescription on Windows.
         */
-       const LogString threadUserName;
+       const LogString& threadUserName;
 };
 
 IMPLEMENT_LOG4CXX_OBJECT(LoggingEvent)
@@ -297,40 +302,64 @@ LoggingEvent::KeySet LoggingEvent::getPropertyKeySet() 
const
 }
 
 
-const LogString LoggingEvent::getCurrentThreadName()
+const LogString& LoggingEvent::getCurrentThreadName()
 {
-#if APR_HAS_THREADS
-       LOG4CXX_THREAD_LOCAL LogString thread_name;
+#if defined(_WIN32)
+       using ThreadIdType = DWORD;
+       ThreadIdType threadId = GetCurrentThreadId();
+#elif APR_HAS_THREADS
+       using ThreadIdType = apr_os_thread_t;
+       ThreadIdType threadId = apr_os_thread_current();
+#else
+       using ThreadIdType = int;
+       ThreadIdType threadId = 0;
+#endif
 
-       if ( thread_name.size() )
+#if LOG4CXX_HAS_THREAD_LOCAL
+       thread_local LogString thread_id_string;
+#else
+       using ListItem = std::pair<ThreadIdType, LogString>;
+       static std::list<ListItem> thread_id_map;
+       static std::mutex mutex;
+       std::lock_guard<std::mutex> lock(mutex);
+       auto pThreadId = std::find_if(thread_id_map.begin(), thread_id_map.end()
+               , [threadId](const ListItem& item) { return threadId == 
item.first; });
+       if (thread_id_map.end() == pThreadId)
+               pThreadId = thread_id_map.insert(thread_id_map.begin(), 
ListItem(threadId, LogString()));
+       LogString& thread_id_string = pThreadId->second;
+#endif
+       if ( !thread_id_string.empty() )
        {
-               return thread_name;
+               return thread_id_string;
        }
 
+#if APR_HAS_THREADS
 #if defined(_WIN32)
        char result[20];
-       DWORD threadId = GetCurrentThreadId();
        apr_snprintf(result, sizeof(result), LOG4CXX_WIN32_THREAD_FMTSPEC, 
threadId);
 #else
        // apr_os_thread_t encoded in HEX takes needs as many characters
        // as two times the size of the type, plus an additional null byte.
        char result[sizeof(apr_os_thread_t) * 3 + 10];
-       apr_os_thread_t threadId = apr_os_thread_current();
        apr_snprintf(result, sizeof(result), LOG4CXX_APR_THREAD_FMTSPEC, 
(void*) &threadId);
 #endif /* _WIN32 */
 
-       log4cxx::helpers::Transcoder::decode(reinterpret_cast<const 
char*>(result), thread_name);
+       log4cxx::helpers::Transcoder::decode(reinterpret_cast<const 
char*>(result), thread_id_string);
 
-       return thread_name;
 #else
-       return LOG4CXX_STR("0x00000000");
+    thread_id_string = LOG4CXX_STR("0x00000000");
 #endif /* APR_HAS_THREADS */
+       return thread_id_string;
 }
 
-const LogString LoggingEvent::getCurrentThreadUserName()
+const LogString& LoggingEvent::getCurrentThreadUserName()
 {
-       LOG4CXX_THREAD_LOCAL LogString thread_name;
-       if( thread_name.size() ){
+#if LOG4CXX_HAS_THREAD_LOCAL
+       thread_local LogString thread_name;
+#else
+       static LogString thread_name = LOG4CXX_STR("(noname)");
+#endif
+       if( !thread_name.empty() ){
                return thread_name;
        }
 
diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt
index d21ecdac..a2558309 100644
--- a/src/main/include/CMakeLists.txt
+++ b/src/main/include/CMakeLists.txt
@@ -108,6 +108,10 @@ CHECK_FUNCTION_EXISTS(wcstombs HAS_WCSTOMBS)
 CHECK_FUNCTION_EXISTS(fwide HAS_FWIDE)
 CHECK_LIBRARY_EXISTS(esmtp smtp_create_session "" HAS_LIBESMTP)
 CHECK_FUNCTION_EXISTS(syslog HAS_SYSLOG)
+try_compile(HAS_THREAD_LOCAL "${CMAKE_BINARY_DIR}/thread-local-test"
+    "${LOG4CXX_SOURCE_DIR}/src/cmake/test-thread-local.cpp"
+    CXX_STANDARD 11
+    )
 if(UNIX)
     set(CMAKE_REQUIRED_LIBRARIES "pthread")
     CHECK_SYMBOL_EXISTS(pthread_sigmask "signal.h" HAS_PTHREAD_SIGMASK)
@@ -131,16 +135,28 @@ if(WIN32)
     CHECK_SYMBOL_EXISTS(GetThreadDescription "windows.h;processthreadsapi.h" 
HAS_GETTHREADDESCRIPTION)
 endif(WIN32)
 
-foreach(varName HAS_STD_LOCALE  HAS_ODBC  HAS_MBSRTOWCS  HAS_WCSTOMBS  
HAS_FWIDE  HAS_LIBESMTP  HAS_SYSLOG HAS_PTHREAD_SIGMASK HAS_PTHREAD_SETNAME 
HAS_PTHREAD_GETNAME HAS_SETTHREADDESCRIPTION HAS_GETTHREADDESCRIPTION)
+foreach(varName
+  HAS_THREAD_LOCAL
+  HAS_STD_LOCALE
+  HAS_ODBC
+  HAS_MBSRTOWCS
+  HAS_WCSTOMBS
+  HAS_FWIDE
+  HAS_LIBESMTP
+  HAS_SYSLOG
+  HAS_PTHREAD_SIGMASK
+  HAS_PTHREAD_SETNAME
+  HAS_PTHREAD_GETNAME
+  HAS_SETTHREADDESCRIPTION
+  HAS_GETTHREADDESCRIPTION
+  )
   if(${varName} EQUAL 0)
     continue()
   elseif(${varName} EQUAL 1)
     continue()
-  elseif("${varName}" STREQUAL "ON")
+  elseif("${varName}" STREQUAL "ON" OR "${varName}" STREQUAL "TRUE")
     set(${varName} 1 )
-  elseif("${varName}" STREQUAL "OFF")
-    set(${varName} 0 )
-  else()
+ else()
     set(${varName} 0 )
   endif()
 endforeach()
diff --git a/src/main/include/log4cxx/private/log4cxx_private.h.in 
b/src/main/include/log4cxx/private/log4cxx_private.h.in
index 55c6844e..9eb5ec23 100644
--- a/src/main/include/log4cxx/private/log4cxx_private.h.in
+++ b/src/main/include/log4cxx/private/log4cxx_private.h.in
@@ -62,15 +62,6 @@
 #define LOG4CXX_HAS_PTHREAD_GETNAME @HAS_PTHREAD_GETNAME@
 #define LOG4CXX_HAS_SETTHREADDESCRIPTION @HAS_SETTHREADDESCRIPTION@
 #define LOG4CXX_HAS_GETTHREADDESCRIPTION @HAS_GETTHREADDESCRIPTION@
-
-#ifdef __BORLANDC__
-/*
- * embarcadero/RAD Studio compilers don't support thread_local:
- * 
http://docwiki.embarcadero.com/RADStudio/Sydney/en/Modern_C%2B%2B_Language_Features_Compliance_Status
- */
-#define LOG4CXX_THREAD_LOCAL
-#else
-#define LOG4CXX_THREAD_LOCAL thread_local
-#endif
+#define LOG4CXX_HAS_THREAD_LOCAL @HAS_THREAD_LOCAL@
 
 #endif
diff --git a/src/main/include/log4cxx/spi/loggingevent.h 
b/src/main/include/log4cxx/spi/loggingevent.h
index d036f40b..55816aef 100644
--- a/src/main/include/log4cxx/spi/loggingevent.h
+++ b/src/main/include/log4cxx/spi/loggingevent.h
@@ -182,8 +182,8 @@ class LOG4CXX_EXPORT LoggingEvent :
                //
                LoggingEvent(const LoggingEvent&);
                LoggingEvent& operator=(const LoggingEvent&);
-               static const LogString getCurrentThreadName();
-               static const LogString getCurrentThreadUserName();
+               static const LogString& getCurrentThreadName();
+               static const LogString& getCurrentThreadUserName();
 
 };
 
diff --git a/src/test/cpp/helpers/timezonetestcase.cpp 
b/src/test/cpp/helpers/timezonetestcase.cpp
index cdbe58af..c15200a0 100644
--- a/src/test/cpp/helpers/timezonetestcase.cpp
+++ b/src/test/cpp/helpers/timezonetestcase.cpp
@@ -38,9 +38,7 @@ LOGUNIT_CLASS(TimeZoneTestCase)
        LOGUNIT_TEST_SUITE(TimeZoneTestCase);
        LOGUNIT_TEST(test1);
        LOGUNIT_TEST(test2);
-#if !defined(__BORLANDC__)
        LOGUNIT_TEST(test3);
-#endif
        LOGUNIT_TEST(test4);
        LOGUNIT_TEST(test5);
        LOGUNIT_TEST(test6);

Reply via email to