作者:Jarosław Kowalski <jaak@jkowalski.net>
概述
日志的记录有时也要化为颇为可观的时间。本文的目的就是揭开日志记录的内部机理并提供一些有用的技巧帮助使用者优化日志记录的性能。
日志记录过程分析
每条日志信息的记录都需要经过一系列的步骤才能完成,其中包括诸如检查消息是否需要被记录以及输出到哪里等。每一条日志的记录都包括以下这些操作:
- 准备日志参数。这是由(.NET/Mono)的公共语言运行时完成的,通常由于一些内部的装箱和数组的操作会导致一些性能上的损失。
- 日志参数准备好以后就可以调用相应的日志方法(
Debug(), Info(), Warn(), Error(), Fatal()
orLog()
)。 - 日志方法以极快的速度检查该日志在该级别的输出是否已经被允许。由于使用了合适的数据结构,这一操作的速度很快。
- 即使成功通过上一步的检查,日志消息还是有可能不会被记录 – 过滤器的检查不通过的话消息就会被拒绝记录。注意,这一步可能很耗时。
- 经过上述几个操作,日志消息被允许记录了 – 这是要根据消息和传递给日志记录方法的参数对消息进行格式化。由于
String.Format
并不快,这一操作可能会很慢。 - 最后一步就是把日志发送给一个或多个需要写入的输出目标。这通常是最慢的一个操作,主要是因为写入的目标通常是一些持久性的存储(文件,数据库)设备,向这些设备写入数据很花时间。
“太糟糕了…”,这可能是你现在的想法吧。不过幸运的是NLog提供了许多编程方面的机制来给日志记录提速。
性能优化技巧
缓存日志记录者
一旦通过调用LogManager.GetLogger()
方法得到了需要的日志记录者,最好的做法是能够把它保存在什么地方,这样就可以重复使用同一个实例而不需要再次调用LogManager.GetLogger()
。给类声明一个静态的成员是个不错的办法,下面就是一个例子:
}using NLog;
class MyClass {
// storing logger reference in a static variable is clean and fast
static Logger logger = LogManager.GetLogger("MyClass");
static void Main()
{
logger.Debug("This is a debugging message");
// it is not recommended to get the logger and store it in a local variable
Logger logger2 = LogManager.GetLogger("MyClass");
logger2.Debug("This is a debugging message");
}
}
TODO: add more tips here