What is the fastest, DRYest way to (not) log?
The log4net FAQ asks the question What is the fastest way of (not) logging? It outlines two techniques of logging; I will present one more.
The first technique is the slowest of the three, but contains the least amount of code. The following snippet logs a million times and illustrates the first technique:
1: for (int i = 0; i < 1000000; ++i)
2: { 3: log.Debug("Number " + i + new Random(DateTime.Now.Millisecond).Next()); 4: }
The big disadvantage of this technique is this: If debug level logging is disabled, then a lot of time is wasted evaluating the current date, getting a random number and concatenating strings. This is because the parameter to the log.Debug method is evaluated before log.Debug is called. A better way to approach would be the following:
1: for (int i = 0; i < 1000000; ++i)
2: { 3: if (log.IsDebugEnabled)
4: { 5: log.Debug("Number " + i + new Random(DateTime.Now.Millisecond).Next()); 6: }
7: }
This way, if debug level logging is disabled, the cost of evaluating the parameter to log.Debug is not incurred. However, this more efficient technique is not very DRY, as we have to litter our code with if statements every time we want to log.
Another technique (not mentioned in the FAQ) uses anonymous methods. This third technique achieves more DRYness than the second technique, and is just about as fast. The following code snippet illustrates this third technique:
1: private delegate string ObjectDelegate();
2:
3: private static void LogDebug(ObjectDelegate d)
4: { 5: if(log.IsDebugEnabled)
6: { 7: log.Debug(d());
8: }
9: }
10:
11: .
12:
13: .
14:
15: for (int i = 0; i < 1000000; ++i)
16: { 17: LogDebug(delegate { return "Number " + i + new Random(DateTime.Now.Millisecond).Next(); }); 18: }
19:
How do these techniques match up performance wise? I've written a small console application that measures how long each of these techniques take to not log 1,000,000 times. I ran the application 10 times, and here are the results (in milliseconds):
| Slow yet DRY technique |
Fast, not DRY technique |
Fast, DRY technique |
| 156 |
62 |
78 |
| 375 |
78 |
78 |
| 343 |
78 |
78 |
| 968 |
93 |
78 |
| 843 |
62 |
78 |
| 234 |
93 |
62 |
| 187 |
78 |
78 |
| 265 |
62 |
78 |
| 328 |
78 |
62 |
| 281 |
62 |
78 |