Skip to content

Commit 92bd7dc

Browse files
committed
Refactor to recover lost performance
1 parent 4b8133a commit 92bd7dc

File tree

4 files changed

+116
-117
lines changed

4 files changed

+116
-117
lines changed

src/main/cpp/loggingevent.cpp

Lines changed: 31 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,23 @@
2828
#endif
2929
#include <log4cxx/helpers/aprinitializer.h>
3030
#include <log4cxx/helpers/threadspecificdata.h>
31-
#include <log4cxx/helpers/transcoder.h>
32-
33-
#include <apr_portable.h>
34-
#include <apr_strings.h>
35-
#include <log4cxx/helpers/stringhelper.h>
3631
#include <log4cxx/helpers/bytebuffer.h>
37-
#include <log4cxx/logger.h>
38-
#include <log4cxx/private/log4cxx_private.h>
3932
#include <log4cxx/helpers/date.h>
4033
#include <log4cxx/helpers/optional.h>
41-
#include <thread>
4234

4335
using namespace LOG4CXX_NS;
4436
using namespace LOG4CXX_NS::spi;
4537
using namespace LOG4CXX_NS::helpers;
4638

4739
struct LoggingEvent::LoggingEventPrivate
4840
{
49-
LoggingEventPrivate() :
41+
LoggingEventPrivate(const ThreadSpecificData::NamePairPtr& p = ThreadSpecificData::getCurrentData()->getNames()) :
5042
timeStamp(0),
51-
threadName(getCurrentThreadName()),
52-
threadUserName(getCurrentThreadUserName())
43+
#if LOG4CXX_ABI_VERSION <= 15
44+
threadName(p->idString),
45+
threadUserName(p->threadName),
46+
#endif
47+
pNames(p)
5348
{
5449
}
5550

@@ -58,29 +53,38 @@ struct LoggingEvent::LoggingEventPrivate
5853
, const LevelPtr& level1
5954
, const LocationInfo& locationInfo1
6055
, LogString&& message1
56+
, const ThreadSpecificData::NamePairPtr& p = ThreadSpecificData::getCurrentData()->getNames()
6157
) :
6258
logger(logger1),
6359
level(level1),
6460
message(std::move(message1)),
6561
timeStamp(Date::currentTime()),
6662
locationInfo(locationInfo1),
67-
threadName(getCurrentThreadName()),
68-
threadUserName(getCurrentThreadUserName()),
69-
chronoTimeStamp(std::chrono::microseconds(timeStamp))
63+
#if LOG4CXX_ABI_VERSION <= 15
64+
threadName(p->idString),
65+
threadUserName(p->threadName),
66+
#endif
67+
chronoTimeStamp(std::chrono::microseconds(timeStamp)),
68+
pNames(p)
7069
{
7170
}
7271

7372
LoggingEventPrivate(
7473
const LogString& logger1, const LevelPtr& level1,
75-
const LogString& message1, const LocationInfo& locationInfo1) :
74+
const LogString& message1, const LocationInfo& locationInfo1,
75+
const ThreadSpecificData::NamePairPtr& p = ThreadSpecificData::getCurrentData()->getNames()
76+
) :
7677
logger(logger1),
7778
level(level1),
7879
message(message1),
7980
timeStamp(Date::currentTime()),
8081
locationInfo(locationInfo1),
81-
threadName(getCurrentThreadName()),
82-
threadUserName(getCurrentThreadUserName()),
83-
chronoTimeStamp(std::chrono::microseconds(timeStamp))
82+
#if LOG4CXX_ABI_VERSION <= 15
83+
threadName(p->idString),
84+
threadUserName(p->threadName),
85+
#endif
86+
chronoTimeStamp(std::chrono::microseconds(timeStamp)),
87+
pNames(p)
8488
{
8589
}
8690

@@ -138,6 +142,7 @@ struct LoggingEvent::LoggingEventPrivate
138142
const spi::LocationInfo locationInfo;
139143

140144

145+
#if LOG4CXX_ABI_VERSION <= 15
141146
/** The identifier of thread in which this logging event
142147
was generated.
143148
*/
@@ -149,24 +154,25 @@ struct LoggingEvent::LoggingEventPrivate
149154
* systems or SetThreadDescription on Windows.
150155
*/
151156
const LogString& threadUserName;
157+
#endif
152158

153159
std::chrono::time_point<std::chrono::system_clock> chronoTimeStamp;
154160

155161
/**
156162
* This ensures the above string references remain valid
157163
* for the lifetime of this LoggingEvent (i.e. even after thread termination).
158164
*/
159-
ThreadSpecificData::OtherDataPtr pNames = ThreadSpecificData::getCurrentData()->getOtherData();
165+
ThreadSpecificData::NamePairPtr pNames;
160166

161-
/**
162-
* Used to hold the diagnostic context when the lifetime
163-
* of this LoggingEvent exceeds the duration of the logging request.
164-
*/
165167
struct DiagnosticContext
166168
{
167169
Optional<NDC::DiagnosticContext> ctx;
168170
MDC::Map map;
169171
};
172+
/**
173+
* Used to hold the diagnostic context when the lifetime
174+
* of this LoggingEvent exceeds the duration of the logging request.
175+
*/
170176
mutable std::unique_ptr<DiagnosticContext> dc;
171177
};
172178

@@ -209,7 +215,7 @@ LoggingEvent::~LoggingEvent()
209215

210216
const LogString& LoggingEvent::getThreadUserName() const
211217
{
212-
return m_priv->threadUserName;
218+
return m_priv->pNames->threadName;
213219
}
214220

215221
bool LoggingEvent::getNDC(LogString& dest) const
@@ -311,82 +317,6 @@ LoggingEvent::KeySet LoggingEvent::getPropertyKeySet() const
311317
return set;
312318
}
313319

314-
315-
const LogString& LoggingEvent::getCurrentThreadName()
316-
{
317-
LogString& thread_id_string = ThreadSpecificData::getThreadIdString();
318-
if ( !thread_id_string.empty() )
319-
{
320-
return thread_id_string;
321-
}
322-
323-
#if LOG4CXX_HAS_PTHREAD_SELF && !(defined(_WIN32) && defined(_LIBCPP_VERSION))
324-
// pthread_t encoded in HEX takes needs as many characters
325-
// as two times the size of the type, plus an additional null byte.
326-
auto threadId = pthread_self();
327-
char result[sizeof(pthread_t) * 3 + 10];
328-
apr_snprintf(result, sizeof(result), LOG4CXX_APR_THREAD_FMTSPEC, (void*) &threadId);
329-
thread_id_string = Transcoder::decode(result);
330-
#elif defined(_WIN32)
331-
char result[20];
332-
apr_snprintf(result, sizeof(result), LOG4CXX_WIN32_THREAD_FMTSPEC, GetCurrentThreadId());
333-
thread_id_string = Transcoder::decode(result);
334-
#else
335-
std::stringstream ss;
336-
ss << std::hex << "0x" << std::this_thread::get_id();
337-
thread_id_string = Transcoder::decode(ss.str().c_str());
338-
#endif
339-
return thread_id_string;
340-
}
341-
342-
const LogString& LoggingEvent::getCurrentThreadUserName()
343-
{
344-
LogString& thread_name = ThreadSpecificData::getThreadName();
345-
if( !thread_name.empty() ){
346-
return thread_name;
347-
}
348-
349-
#if LOG4CXX_HAS_PTHREAD_GETNAME && !(defined(_WIN32) && defined(_LIBCPP_VERSION))
350-
char result[16];
351-
pthread_t current_thread = pthread_self();
352-
if (pthread_getname_np(current_thread, result, sizeof(result)) < 0 || 0 == result[0])
353-
thread_name = getCurrentThreadName();
354-
else
355-
thread_name = Transcoder::decode(result);
356-
#elif defined(_WIN32)
357-
typedef HRESULT (WINAPI *TGetThreadDescription)(HANDLE, PWSTR*);
358-
static struct initialiser
359-
{
360-
HMODULE hKernelBase;
361-
TGetThreadDescription GetThreadDescription;
362-
initialiser()
363-
: hKernelBase(GetModuleHandleA("KernelBase.dll"))
364-
, GetThreadDescription(nullptr)
365-
{
366-
if (hKernelBase)
367-
GetThreadDescription = reinterpret_cast<TGetThreadDescription>(GetProcAddress(hKernelBase, "GetThreadDescription"));
368-
}
369-
} win32func;
370-
if (win32func.GetThreadDescription)
371-
{
372-
PWSTR result = 0;
373-
HRESULT hr = win32func.GetThreadDescription(GetCurrentThread(), &result);
374-
if (SUCCEEDED(hr) && result)
375-
{
376-
std::wstring wresult = result;
377-
LOG4CXX_DECODE_WCHAR(decoded, wresult);
378-
LocalFree(result);
379-
thread_name = decoded;
380-
}
381-
}
382-
if (thread_name.empty())
383-
thread_name = getCurrentThreadName();
384-
#else
385-
thread_name = getCurrentThreadName();
386-
#endif
387-
return thread_name;
388-
}
389-
390320
void LoggingEvent::setProperty(const LogString& key, const LogString& value)
391321
{
392322
if (m_priv->properties == 0)
@@ -419,7 +349,7 @@ const LogString& LoggingEvent::getRenderedMessage() const
419349

420350
const LogString& LoggingEvent::getThreadName() const
421351
{
422-
return m_priv->threadName;
352+
return m_priv->pNames->idString;
423353
}
424354

425355
log4cxx_time_t LoggingEvent::getTimeStamp() const

src/main/cpp/threadspecificdata.cpp

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
#include <log4cxx/logstring.h>
2020
#include <log4cxx/helpers/threadspecificdata.h>
2121
#include <log4cxx/helpers/exception.h>
22+
#include <log4cxx/helpers/stringhelper.h>
23+
#include <log4cxx/helpers/transcoder.h>
2224
#include <apr_thread_proc.h>
25+
#include <apr_strings.h>
2326
#if !defined(LOG4CXX)
2427
#define LOG4CXX 1
2528
#endif
@@ -32,18 +35,17 @@
3235
using namespace LOG4CXX_NS;
3336
using namespace LOG4CXX_NS::helpers;
3437

35-
struct ThreadSpecificData::OtherData : public std::pair<LogString, LogString>
36-
{
37-
};
38-
3938
struct ThreadSpecificData::ThreadSpecificDataPrivate{
4039
ThreadSpecificDataPrivate()
41-
: pOtherData(std::make_shared<OtherData>())
42-
{}
40+
: pNamePair(std::make_shared<NamePair>())
41+
{
42+
setThreadIdName();
43+
setThreadUserName();
44+
}
4345
NDC::Stack ndcStack;
4446
MDC::Map mdcMap;
4547

46-
std::shared_ptr<OtherData> pOtherData;
48+
std::shared_ptr<NamePair> pNamePair;
4749

4850
#if !LOG4CXX_LOGCHAR_IS_UNICHAR && !LOG4CXX_LOGCHAR_IS_WCHAR
4951
std::basic_ostringstream<logchar> logchar_stringstream;
@@ -54,8 +56,73 @@ struct ThreadSpecificData::ThreadSpecificDataPrivate{
5456
#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
5557
std::basic_ostringstream<UniChar> unichar_stringstream;
5658
#endif
59+
60+
void setThreadIdName();
61+
void setThreadUserName();
5762
};
5863

64+
void ThreadSpecificData::ThreadSpecificDataPrivate::setThreadIdName()
65+
{
66+
#if LOG4CXX_HAS_PTHREAD_SELF && !(defined(_WIN32) && defined(_LIBCPP_VERSION))
67+
// pthread_t encoded in HEX takes needs as many characters
68+
// as two times the size of the type, plus an additional null byte.
69+
auto threadId = pthread_self();
70+
char result[sizeof(pthread_t) * 3 + 10];
71+
apr_snprintf(result, sizeof(result), LOG4CXX_APR_THREAD_FMTSPEC, (void*) &threadId);
72+
this->pNamePair->idString = Transcoder::decode(result);
73+
#elif defined(_WIN32)
74+
char result[20];
75+
apr_snprintf(result, sizeof(result), LOG4CXX_WIN32_THREAD_FMTSPEC, GetCurrentThreadId());
76+
this->pNamePair->idString = Transcoder::decode(result);
77+
#else
78+
std::stringstream ss;
79+
ss << std::hex << "0x" << std::this_thread::get_id();
80+
this->pNamePair->idString = Transcoder::decode(ss.str().c_str());
81+
#endif
82+
}
83+
84+
void ThreadSpecificData::ThreadSpecificDataPrivate::setThreadUserName()
85+
{
86+
#if LOG4CXX_HAS_PTHREAD_GETNAME && !(defined(_WIN32) && defined(_LIBCPP_VERSION))
87+
char result[16];
88+
pthread_t current_thread = pthread_self();
89+
if (pthread_getname_np(current_thread, result, sizeof(result)) < 0 || 0 == result[0])
90+
this->pNamePair->threadName = this->pNamePair->idString;
91+
else
92+
this->pNamePair->threadName = Transcoder::decode(result);
93+
#elif defined(_WIN32)
94+
typedef HRESULT (WINAPI *TGetThreadDescription)(HANDLE, PWSTR*);
95+
static struct initialiser
96+
{
97+
HMODULE hKernelBase;
98+
TGetThreadDescription GetThreadDescription;
99+
initialiser()
100+
: hKernelBase(GetModuleHandleA("KernelBase.dll"))
101+
, GetThreadDescription(nullptr)
102+
{
103+
if (hKernelBase)
104+
GetThreadDescription = reinterpret_cast<TGetThreadDescription>(GetProcAddress(hKernelBase, "GetThreadDescription"));
105+
}
106+
} win32func;
107+
if (win32func.GetThreadDescription)
108+
{
109+
PWSTR result = 0;
110+
HRESULT hr = win32func.GetThreadDescription(GetCurrentThread(), &result);
111+
if (SUCCEEDED(hr) && result)
112+
{
113+
std::wstring wresult = result;
114+
LOG4CXX_DECODE_WCHAR(decoded, wresult);
115+
LocalFree(result);
116+
this->pNamePair->threadName = decoded;
117+
}
118+
}
119+
if (this->pNamePair->threadName.empty())
120+
this->pNamePair->threadName = this->pNamePair->idString;
121+
#else
122+
this->pNamePair->threadName = this->pNamePair->idString;
123+
#endif
124+
}
125+
59126
ThreadSpecificData::ThreadSpecificData()
60127
: m_priv(std::make_unique<ThreadSpecificDataPrivate>())
61128
{
@@ -82,17 +149,17 @@ MDC::Map& ThreadSpecificData::getMap()
82149

83150
LogString& ThreadSpecificData::getThreadIdString()
84151
{
85-
return getCurrentData()->m_priv->pOtherData->first;
152+
return getCurrentData()->m_priv->pNamePair->idString;
86153
}
87154

88155
LogString& ThreadSpecificData::getThreadName()
89156
{
90-
return getCurrentData()->m_priv->pOtherData->second;
157+
return getCurrentData()->m_priv->pNamePair->threadName;
91158
}
92159

93-
auto ThreadSpecificData::getOtherData() -> OtherDataPtr
160+
auto ThreadSpecificData::getNames() -> NamePairPtr
94161
{
95-
return getCurrentData()->m_priv->pOtherData;
162+
return getCurrentData()->m_priv->pNamePair;
96163
}
97164

98165
#if !LOG4CXX_LOGCHAR_IS_UNICHAR && !LOG4CXX_LOGCHAR_IS_WCHAR

src/main/include/log4cxx/helpers/threadspecificdata.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,19 @@ class LOG4CXX_EXPORT ThreadSpecificData
6161
static LogString& getThreadIdString();
6262
static LogString& getThreadName();
6363

64+
struct NamePair
65+
{
66+
LogString idString;
67+
LogString threadName;
68+
};
69+
using NamePairPtr = std::shared_ptr<NamePair>;
6470
/**
6571
* A reference counted pointer to thread specific strings.
6672
*
6773
* String references will remain valid
6874
* for the lifetime of this pointer (i.e. even after thread termination).
6975
*/
70-
struct OtherData;
71-
using OtherDataPtr = std::shared_ptr<OtherData>;
72-
static OtherDataPtr getOtherData();
76+
static NamePairPtr getNames();
7377
private:
7478
#if !LOG4CXX_LOGCHAR_IS_UNICHAR && !LOG4CXX_LOGCHAR_IS_WCHAR
7579
static std::basic_ostringstream<logchar>& getStream(const logchar&);

src/main/include/log4cxx/spi/loggingevent.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,6 @@ class LOG4CXX_EXPORT LoggingEvent :
212212
//
213213
LoggingEvent(const LoggingEvent&);
214214
LoggingEvent& operator=(const LoggingEvent&);
215-
static const LogString& getCurrentThreadName();
216-
static const LogString& getCurrentThreadUserName();
217215

218216
};
219217

0 commit comments

Comments
 (0)