On Mar 19, 2006, at 1:40 AM, Jaroslaw Kowalski wrote:
> Small hint from NLog developer:
>
> Why don't you pass the raw message with parameter
placeholders,
> format arguments and IFormatProvider down to the
logging engine and
> defer calling the actual String.Format to as late as
possible?
> This way you can avoid the cost of String.Format() at
all if there
> are filters (or whatever) which cause the message to be
ignored,
> while IsXXXEnabled would return true.
>
Since ILog.Debug and similar take an object as the message
parameter,
it should be fairly easy to construct an object from the
IFormatProvider and parameters and overload ToString() to
call
IFormatProvider.Format. I didn't pursue that optimization
with the
log4j sandbox effort, though I didn't preclude it either.
> One thing that you need to be aware of is the possible
reentrancy
> problem, since format arguments may be objects which
override
> ToString() and which do the logging inside this method.
Things can
> get weird if you call logging code in the middle of
logging (mostly
> because of locking and thread-locality issues), but
this is
> something that can be quite easily sorted out.
>
> I'm not sure if this can be easily done in log4net,
though.
Those have been issues when passing non-String messages with
log4j.
Ideally, ToString() would be called before acquiring any
significant
locks and before handing the event off to another thread.
On Mar 19, 2006, at 11:12 AM, Nicko Cadell wrote:
> It is also worth mentioning that, unlike log4j, in
log4net the user
> does
> not interact with the Logger directly but with a
wrapper. The Logger
> (ILogger) has a Log method that is used to log all the
messages. The
> wrapper LogImpl (implements ILog) has all the
Debug/Info/Warn/Error
> methods which forward the log call to the Logger
method. The LogImpl
> contains the Format methods. If a use wants a different
format
> implementation they can write their own wrapper with
user callable
> methods.
> Nicko
I've quickly reviewed the log4net source code. One of the
design
concerns in the log4j sandbox effort was avoiding array
creation or
boxing costs for requests that were below the threshold.
The
ILog.DebugFormat and similar methods would appear to incur
boxing and
array creation cost even if the message was below the
threshold. In
performance testing on Java, those costs were non-trivial.
Ideally,
you would like the cost of a below threshold log request to
be only
the cost of logger.IsEnabledFor and to have that cost as
small as
possible.
You do have that advantage of having a common interface in
IFormatProvider which isn't the case in case with
java.text.MessageFormat and java.util.Formatter. So you
may be able
to avoid the cut-and-paste madness of the sandbox
implementation if
you want to support multiple formatters.
The sandbox effort also tries to perform some optimizations
that may
not be beneficial on .NET. For example, evaluating a simple
pattern
with only plain substitutions is can be done faster than
calling
MessageFormat.format. The optimizations should be
transparent to the
user and do not need to be replicated in a .NET
implementation if
they do not offer a benefit.
I do like the distinct static class approach, it separates
the
logging function from the formatting function but still
allows the
short-circuiting and other performance optimizations that
motivated
combining them.
|