NullAppender:IAppender is about 20% faster than
NullAppender:AppenderSkeleton on my system when calling log.Debug
several million times inside a tight loop:
public class NullAppender : IAppender
{
public void Close()
{
/* empty */
}
public void DoAppend(LoggingEvent loggingEvent)
{
/* empty */
}
public string Name
{
get { return "NullAppender"; }
set { /* empty */ }
}
}
public class NullAppender : AppenderSkeleton
{
protected override void Append(LoggingEvent loggingEvent)
{
/* empty */
}
}
--- Nicko Cadell <[EMAIL PROTECTED]> wrote:
> The AppenderSkeleton uses a lock to ensure that the calls to the
> subclass' Append method are serialised. This makes the job of writing
> a
> custom appender much easier as you don't have to deal with threading.
>
> The FastDbAppender does not use a lock to serialise the calls to the
> Append method, or to the database. The code in the appender is
> designed
> to be thread safe. This thread safe design allow the appender to work
> without a synchronisation lock, this gives an important performance
> enhancement and is a large part of the 'Fast' in FastDbAppender.
>
> It may be that the serialisation guarantees of the AppenderSkeleton
> have
> too much of a performance penalty. Perhaps we should have another
> base
> class that provides the same support functions as the
> AppenderSkeleton
> without the synchronisation locking. If we build this new base class
> cleverly we could also use it as a base for the current
> AppenderSkeleton.
>
> Cheers,
> Nicko
>
> > -----Original Message-----
> > From: Ron Grabowski [mailto:[EMAIL PROTECTED]
> > Sent: 16 July 2006 19:40
> > To: [email protected]
> > Subject: AppenderSkeleton.DoAppender calls lock(this) while
> > some IAppender examples do not
> >
> > Nicko, AppenderSkeleton's IAppender.DoAppender method
> > contains this code and comment:
> >
> > public void DoAppend(LoggingEvent loggingEvent)
> > {
> >
> > // This lock is absolutely critical for correct formatting
> > // of the message in a multi-threaded environment. Without
> > // this, the message may be broken up into elements from
> > // multiple thread contexts (like get the wrong thread ID).
> >
> > lock(this)
> > {
> > // [snip]
> > }
> > }
> >
> > FastDbAppender contains this code:
> >
> > public virtual void DoAppend(LoggingEvent loggingEvent) {
> > using(IDbConnection connection = GetConnection())
> > {
> > // Open the connection for each event, this takes advantage
> > // of the builtin connection pooling
> > connection.Open();
> >
> > using(IDbCommand command = connection.CreateCommand())
> > {
> > InitializeCommand(command);
> >
> > SetCommandValues(command, loggingEvent);
> > command.ExecuteNonQuery();
> > }
> > }
> > }
> >
> > Is it necessary for FastDbAppender to have a lock statement
> > around that code?
> >
> >
>