Skip to content

Commit 4398b68

Browse files
authored
Make AsyncAppender web-site information more accurate (#540)
1 parent 0389045 commit 4398b68

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/main/include/log4cxx/asyncappender.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ to prevent undefined behaviour when using this appender.
4242
4343
This appender is useful when outputting to a slow event sink,
4444
for example, a remote SMTP server or a database.
45-
Attaching a FileAppender to AsyncAppender
46-
to reduce logging overhead is not recommended
45+
Note that configuring a FileAppender to use [buffered output](@ref log4cxx::FileAppender::setOption)
46+
usually results in lower overhead than
47+
attaching the FileAppender to an AsyncAppender
4748
as the inter-thread communication overhead
48-
can exceed the time to write directly to a file.
49+
can exceed the time to add a message to a buffer.
4950
5051
You can attach multiple appenders to an AsyncAppender by:
5152
- calling AsyncAppender::addAppender repeatedly when progammatically configuring Log4cxx.
@@ -58,13 +59,13 @@ Here is a sample configuration file:
5859
5960
### Configurable properties
6061
61-
When the application produces logging events faster
62+
\anchor BlockingProperty When the application produces logging events faster
6263
than the background thread is able to process,
6364
the bounded buffer can become full.
6465
In this situation AsyncAppender will either
6566
block until the bounded buffer has a free slot or
6667
discard the event.
67-
The <b>Blocking</b> property controls which behaviour is used.
68+
The [Blocking property](@ref AsyncAppender::setOption) controls which behaviour is used.
6869
When events are discarded,
6970
the logged output will indicate this
7071
with a log message prefixed with <i>Discarded</i>.
@@ -100,7 +101,7 @@ class LOG4CXX_EXPORT AsyncAppender :
100101
AsyncAppender();
101102

102103
/**
103-
* Destructor.
104+
* If not closed, calls AsyncAppender::close.
104105
*/
105106
virtual ~AsyncAppender();
106107

@@ -112,9 +113,17 @@ class LOG4CXX_EXPORT AsyncAppender :
112113
*/
113114
void addAppender(const AppenderPtr newAppender) override;
114115

116+
/**
117+
* Call AppenderSkeleton#doAppendImpl without acquiring a lock.
118+
*/
115119
void doAppend(const spi::LoggingEventPtr& event,
116120
helpers::Pool& pool1) override;
117121

122+
/**
123+
* Add \c event to a ring buffer.
124+
* The behaviour when the ring buffer is full
125+
* is controlled by the [Blocking property](@ref BlockingProperty) value.
126+
*/
118127
void append(const spi::LoggingEventPtr& event, helpers::Pool& p) override;
119128

120129
/**
@@ -149,6 +158,8 @@ class LOG4CXX_EXPORT AsyncAppender :
149158
*/
150159
bool isAttached(const AppenderPtr appender) const override;
151160

161+
/** Return false
162+
*/
152163
bool requiresLayout() const override;
153164

154165
/**

src/site/markdown/performance.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ The "Iterations" column derivation is explained in [Google Benchmark documentati
103103
| Multiprocess logging int+float using MessageBuffer, pattern: \%d \%m\%n | 3456 ns | 3456 ns | 203235 |
104104

105105
-# The "Appending" benchmarks just format the message (using PatternLayout) then discard the result.
106-
-# The "Async" benchmarks test AsyncAppender throughput, with logging events discarded in the background thread.
106+
-# The "Async" benchmarks test [AsyncAppender](@ref log4cxx::AsyncAppender) throughput, with logging events discarded in the background thread.
107107
-# The "Logging" benchmarks write to a file using buffered output. Overhead is 2-3 times more when not using buffered output.
108108

109109
The above table shows that the overhead of an enabled logging request
@@ -113,8 +113,21 @@ Most importantly note that [using buffered output](@ref log4cxx::FileAppender::s
113113
reduces overhead more than any other detail.
114114

115115
Note also that logging from multiple threads concurrently
116-
to a common appender does not increase throughput due to lock contention.
116+
to a common appender generally does not increase throughput
117+
due to lock contention in [doAppend method](@ref log4cxx::AppenderSkeleton::doAppend).
117118
To simplify the work of an appender implementator,
118119
the [doAppend method](@ref log4cxx::AppenderSkeleton::doAppend) currently prevents multiple threads
119120
concurrently entering [the append method](@ref log4cxx::AppenderSkeleton::append),
120121
which is the method required to be implemented by a concrete appender class.
122+
123+
The [AsyncAppender](@ref log4cxx::AsyncAppender) provides the least overhead
124+
when logging concurrently from multiple threads
125+
as it overrides the [doAppend method](@ref log4cxx::AsyncAppender::doAppend)
126+
and uses [std::atomic](https://en.cppreference.com/w/cpp/atomic/atomic.html)
127+
counters and a ring buffer to store logging events.
128+
A single background thread is used to extract the logging events
129+
from the ring bufffer and send them
130+
to the attached appenders.
131+
This moves the overhead of [the layout method](@ref log4cxx::Layout::format)
132+
and the blocking transfer of message data to the operating system
133+
from the calling thread to the background thread.

0 commit comments

Comments
 (0)