Skip to content

Commit 610018a

Browse files
authored
Reduce logging overhead by reserving storage in the output string (#246)
1 parent cc7235a commit 610018a

File tree

7 files changed

+77
-12
lines changed

7 files changed

+77
-12
lines changed

src/main/cpp/fmtlayout.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,19 @@ using namespace log4cxx;
3131
using namespace log4cxx::spi;
3232

3333
struct FMTLayout::FMTLayoutPrivate{
34-
FMTLayoutPrivate(){}
34+
FMTLayoutPrivate()
35+
: expectedPatternLength(100)
36+
{}
3537

36-
FMTLayoutPrivate(const LogString& pattern) :
37-
conversionPattern(pattern)
38+
FMTLayoutPrivate(const LogString& pattern)
39+
: conversionPattern(pattern)
40+
, expectedPatternLength(100)
3841
{}
3942

4043
LogString conversionPattern;
44+
45+
// Expected length of a formatted event excluding the message text
46+
size_t expectedPatternLength;
4147
};
4248

4349
IMPLEMENT_LOG4CXX_OBJECT(FMTLayout)
@@ -76,13 +82,14 @@ void FMTLayout::setOption(const LogString& option, const LogString& value)
7682

7783
void FMTLayout::activateOptions(helpers::Pool&)
7884
{
79-
85+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
8086
}
8187

8288
void FMTLayout::format(LogString& output,
8389
const spi::LoggingEventPtr& event,
8490
log4cxx::helpers::Pool&) const
8591
{
92+
output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
8693
auto locationFull = fmt::format("{}({})",
8794
event->getLocationInformation().getFileName(),
8895
event->getLocationInformation().getLineNumber());

src/main/cpp/htmllayout.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,22 @@ using namespace log4cxx::spi;
3535

3636
struct HTMLLayout::HTMLLayoutPrivate
3737
{
38-
HTMLLayoutPrivate() : locationInfo(false), title(LOG4CXX_STR("Log4cxx Log Messages")),
39-
dateFormat() {}
38+
HTMLLayoutPrivate()
39+
: locationInfo(false)
40+
, title(LOG4CXX_STR("Log4cxx Log Messages"))
41+
, dateFormat()
42+
, expectedPatternLength(100)
43+
{}
4044

4145
// Print no location info by default
4246
bool locationInfo; //= false
4347

4448
LogString title;
4549

4650
helpers::ISO8601DateFormat dateFormat;
51+
52+
// Expected length of a formatted event excluding the message text
53+
size_t expectedPatternLength;
4754
};
4855

4956
IMPLEMENT_LOG4CXX_OBJECT(HTMLLayout)
@@ -53,6 +60,7 @@ HTMLLayout::HTMLLayout()
5360
: m_priv(std::make_unique<HTMLLayoutPrivate>())
5461
{
5562
m_priv->dateFormat.setTimeZone(TimeZone::getGMT());
63+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
5664
}
5765

5866
HTMLLayout::~HTMLLayout() {}
@@ -71,13 +79,15 @@ void HTMLLayout::setOption(const LogString& option,
7179
LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
7280
{
7381
setLocationInfo(OptionConverter::toBoolean(value, false));
82+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
7483
}
7584
}
7685

7786
void HTMLLayout::format(LogString& output,
7887
const spi::LoggingEventPtr& event,
7988
Pool& p) const
8089
{
90+
output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
8191
output.append(LOG4CXX_EOL);
8292
output.append(LOG4CXX_STR("<tr>"));
8393
output.append(LOG4CXX_EOL);

src/main/cpp/jsonlayout.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ struct JSONLayout::JSONLayoutPrivate
3939
prettyPrint(false),
4040
dateFormat(),
4141
ppIndentL1(LOG4CXX_STR(" ")),
42-
ppIndentL2(LOG4CXX_STR(" ")) {}
42+
ppIndentL2(LOG4CXX_STR(" ")),
43+
expectedPatternLength(100) {}
4344

4445
// Print no location info by default
4546
bool locationInfo; //= false
@@ -49,6 +50,9 @@ struct JSONLayout::JSONLayoutPrivate
4950

5051
LogString ppIndentL1;
5152
LogString ppIndentL2;
53+
54+
// Expected length of a formatted event excluding the message text
55+
size_t expectedPatternLength;
5256
};
5357

5458
JSONLayout::JSONLayout() :
@@ -85,7 +89,7 @@ LogString JSONLayout::getContentType() const
8589

8690
void JSONLayout::activateOptions(helpers::Pool& /* p */)
8791
{
88-
92+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
8993
}
9094

9195
void JSONLayout::setOption(const LogString& option, const LogString& value)
@@ -106,6 +110,7 @@ void JSONLayout::format(LogString& output,
106110
const spi::LoggingEventPtr& event,
107111
Pool& p) const
108112
{
113+
output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
109114
output.append(LOG4CXX_STR("{"));
110115
output.append(m_priv->prettyPrint ? LOG4CXX_EOL : LOG4CXX_STR(" "));
111116

src/main/cpp/layout.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,20 @@ LogString Layout::getContentType() const
3333
void Layout::appendHeader(LogString&, log4cxx::helpers::Pool&) {}
3434

3535
void Layout::appendFooter(LogString&, log4cxx::helpers::Pool&) {}
36+
37+
/**
38+
* The expected length of a formatted event excluding the message text
39+
*/
40+
size_t Layout::getFormattedEventCharacterCount() const
41+
{
42+
auto exampleEvent = std::make_shared<spi::LoggingEvent>
43+
( LOG4CXX_STR("example.logger")
44+
, Level::getDebug()
45+
, LOG4CXX_LOCATION
46+
, LogString()
47+
);
48+
LogString text;
49+
Pool pool;
50+
format(text, exampleEvent, pool);
51+
return text.size();
52+
}

src/main/cpp/patternlayout.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ using namespace log4cxx::pattern;
5757

5858
struct PatternLayout::PatternLayoutPrivate
5959
{
60-
PatternLayoutPrivate() {}
61-
PatternLayoutPrivate(const LogString& pattern) :
62-
conversionPattern(pattern) {}
60+
PatternLayoutPrivate()
61+
: expectedPatternLength(100)
62+
{}
63+
PatternLayoutPrivate(const LogString& pattern)
64+
: conversionPattern(pattern)
65+
, expectedPatternLength(100)
66+
{}
6367

6468
/**
6569
* Conversion pattern.
@@ -82,6 +86,9 @@ struct PatternLayout::PatternLayoutPrivate
8286
LogString m_infoColor = LOG4CXX_STR("\\x1B[32m"); //green
8387
LogString m_debugColor = LOG4CXX_STR("\\x1B[36m"); //cyan;
8488
LogString m_traceColor = LOG4CXX_STR("\\x1B[34m"); //blue;
89+
90+
// Expected length of a formatted event excluding the message text
91+
size_t expectedPatternLength;
8592
};
8693

8794
IMPLEMENT_LOG4CXX_OBJECT(PatternLayout)
@@ -115,6 +122,7 @@ void PatternLayout::format(LogString& output,
115122
const spi::LoggingEventPtr& event,
116123
Pool& pool) const
117124
{
125+
output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
118126
std::vector<FormattingInfoPtr>::const_iterator formatterIter =
119127
m_priv->patternFields.begin();
120128

@@ -199,6 +207,7 @@ void PatternLayout::activateOptions(Pool&)
199207
m_priv->patternConverters.push_back(eventConverter);
200208
}
201209
}
210+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
202211
}
203212

204213
#define RULES_PUT(spec, cls) \

src/main/cpp/xmllayout.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,26 @@ using namespace log4cxx::xml;
3434

3535
struct XMLLayout::XMLLayoutPrivate
3636
{
37-
XMLLayoutPrivate() : locationInfo(false), properties(false) {}
37+
XMLLayoutPrivate()
38+
: locationInfo(false)
39+
, properties(false)
40+
, expectedPatternLength(100)
41+
{}
3842

3943
// Print no location info by default
4044
bool locationInfo; //= false
4145
bool properties; // = false
46+
47+
// Expected length of a formatted event excluding the message text
48+
size_t expectedPatternLength;
4249
};
4350

4451
IMPLEMENT_LOG4CXX_OBJECT(XMLLayout)
4552

4653
XMLLayout::XMLLayout()
4754
: m_priv(std::make_unique<XMLLayoutPrivate>())
4855
{
56+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
4957
}
5058

5159
XMLLayout::~XMLLayout() {}
@@ -56,18 +64,21 @@ void XMLLayout::setOption(const LogString& option,
5664
if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
5765
{
5866
setLocationInfo(OptionConverter::toBoolean(value, false));
67+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
5968
}
6069

6170
if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PROPERTIES"), LOG4CXX_STR("properties")))
6271
{
6372
setProperties(OptionConverter::toBoolean(value, false));
73+
m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
6474
}
6575
}
6676

6777
void XMLLayout::format(LogString& output,
6878
const spi::LoggingEventPtr& event,
6979
Pool& p) const
7080
{
81+
output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
7182
output.append(LOG4CXX_STR("<log4j:event logger=\""));
7283
Transform::appendEscapingTags(output, event->getLoggerName());
7384
output.append(LOG4CXX_STR("\" timestamp=\""));

src/main/include/log4cxx/layout.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ class LOG4CXX_EXPORT Layout :
7575
The other layouts return <code>false</code>.
7676
*/
7777
virtual bool ignoresThrowable() const = 0;
78+
79+
protected:
80+
/**
81+
* The expected length of a formatted event excluding the message text
82+
*/
83+
size_t getFormattedEventCharacterCount() const;
7884
};
7985
LOG4CXX_PTR_DEF(Layout);
8086
}

0 commit comments

Comments
 (0)