Hi list, hi Ron!
first, thank you Ron for your detailed answer.
> It sounds like designing and implementing your own interface
> (using ILog as a guide) might suit your needs better. Here is
> an example of an
That's exactly true. If I understand it correctly, we can then
simply provide our own customized ILog, LogImpl and LogManager.
That's really nice :-)
> Don't you think code like this would be difficult to maintain?
>
> log.FatalIf(temp, "Hello World");
One would typically write
log.WarnIf(room == null, "No room defined for ...");
simply as a "syntactic sugar" replacement for
if (room == null) {
log.Warn(...)
}
There are already plenty of locations in our code where we use
conditional calls. But with an own ILog, LogImpl, LogManager,
we can address that :-)
> If speed is an issue in your project you may need to look
> into certain optimizations that will be more applicatable for
> your project. Jaroslaw Kowalski, the author of NLog, states
> that log4net takes between 50-60 nanoseconds
His implementation takes 5-10 microseconds to log to a file, and
he says that NLog is faster than log4net. I can't imagine that
anything useful can happen in only 50ns ;-)
I don't matter whether a statement takes 5 microseconds or 6, but
if it's easy to improve performance by a significant amount, then
why not do it? In my opinion, two points in log4net are more
time-expensive than they have to be:
- the first is how the constructor of LocationInfo determines the
user method that invoked the logging command:
System.Reflection.MethodBase method = locationFrame.GetMethod();
StackFrame.GetMethod() is about ten times slower than
MethodBase.GetCurrentMethod() (see our performance test at the
end), so passing the latter as an argument into the logging
method could be an interesting option, like in
log.Error(MethodBase.GetCurrentMethod(), "xxxxx");
- and the second one is in LoggingEvent to get the user name:
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
People who need the user identity in their log message could
add it as a context property. Like this, you could avoid the
negative impact on those who don't need it.
Greetings,
Andy
--
Cost of getting the current method
Getting the current method through MethodBase.GetCurrentMethod() is
preferred over using StackFrame(0).GetMethod(), the latter being around 10
times slower. The reason for this is that instantiating a StackFrame object
implies building the entire stack trace for the current call context.
Obtaining the caller ("parent") method, through StackFrame(1).GetMethod() is
then only slightly slower than getting the current method since the
StackFrame has already been created.
private void Dummy() {
MethodBase m = new StackFrame(1).GetMethod();
}
[Benchmark("MethodBase.GetCurrentMethod()")]
public void BenchmarkMethodBase() {
for (int i = 0; i < Iterations; i++) {
MethodBase m = MethodBase.GetCurrentMethod();
}
}
[Benchmark("StackFrame(0).GetMethod()")]
public void BenchmarkStackFrame0() {
for (int i = 0; i < Iterations; i++) {
MethodBase m = new StackFrame(0).GetMethod();
}
}
[Benchmark("StackFrame(1).GetMethod() (submethod)")]
public void BenchmarkStackFrame1() {
for (int i = 0; i < Iterations; i++) {
Dummy();
}
}
Benchmark Score
MethodBase.GetCurrentMethod() 16651
new StackFrame?(0).GetMethod() 121803
new StackFrame?(1).GetMethod() 122174