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

Reply via email to