> -----Original Message-----
> From: Curt Arnold [mailto:carnold apache.org] Sent: 19 March
2006
22:34
>
> 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.
I think this would be a worthwhile performance improvement
to make.
> 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.
It looks like the log4j sandbox and the .net framework agree
on the
number of override params, 3. This gives signatures like:
void DebugFormat(string format);
void DebugFormat(string format, object arg0);
void DebugFormat(string format, object arg0, object arg1);
void DebugFormat(string format, object arg0, object arg1,
object arg2);
void DebugFormat(string format, params object[] args);
> 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.
These optimisations may be added later transparently to the
user.
> 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.
In that case why not move the Debug, Info, Warn etc..
methods into a
static class?
Log.Debug(logger, message);
Then your logger only needs to have a single method that
takes a Level,
and a message. This has the advantage that a user easily
understands how
to add support for their own levels or different logging
method
signatures, for example:
MyLog.Alarm(logger, message, state);
In addition using the extension methods proposed feature of
C# 3 it
would be possible to decorate the logger with these methods
allowing you
to call logger.Alarm(message, state);
log4net has chosen a slightly different design which is to
support
wrapper objects that provide the interface to the logger.
The Debug,
Info, Warn etc.. methods are on a simple wrapper object that
forwards to
the nested logger. This design does give us the nice syntax
of
logger.Debug(message) but it does make it harder for the
user to
understand how to add their own log methods, and there is a
higher
memory cost for having the additional wrapper around the
nested logger.
I think that given this historic design decision we should
not introduce
a static class of logging helper methods at this time, as
that would
confuse users further. Removing the current xxxFormat
methods from the
ILog interface will break a number of early adopters, which
I would
rather avoid if possible.
I propose adding format method overrides (see above) for
common numbers
of format param arguments. And also wrapping the format
message in an
object to delay the formatting of the message until after
the appender
filters have run.
Nicko
|