C# log4net性能:我应该在尝试登录之前检查日志级别吗?
如果log4net配置中的日志级别设置为Info-level,您是否希望下面的A)或B)具有更好的性能?_log.Debug会自己执行更多代码并花费更长时间吗 (A) (B)C# log4net性能:我应该在尝试登录之前检查日志级别吗?,c#,log4net,C#,Log4net,如果log4net配置中的日志级别设置为Info-level,您是否希望下面的A)或B)具有更好的性能?_log.Debug会自己执行更多代码并花费更长时间吗 (A) (B) 在这种情况下,我会使用B 但是,如果构造日志消息(log.Debug的参数)可能需要一段时间(例如,涉及重要的字符串连接),那么我会选择a。在“yes,log It”的情况下,它将执行相同的测试两次,但不需要在“no,don't log It”的情况下构造日志消息案例。即使第一个选项的性能稍微好一点,我也不会太担心 但是,
在这种情况下,我会使用B
但是,如果构造日志消息(log.Debug的参数)可能需要一段时间(例如,涉及重要的字符串连接),那么我会选择a。在“yes,log It”的情况下,它将执行相同的测试两次,但不需要在“no,don't log It”的情况下构造日志消息案例。即使第一个选项的性能稍微好一点,我也不会太担心 但是,如果您这样做:
_log.Debug(String.Format("{0} {1} {2}...", param1, param2, param3));
if (_log.IsDebugEnabled())
{
var message = createComplicatedLogMessageThatTakesALotOfTime();
_log.Debug(message);
}
然后,有一个很好的理由可以检查之前启用的_log.IsDebugEnabled。我会选择选项B,除非日志消息本身需要很长时间来构造。通常情况下,性能增益可以忽略不计,甚至根本不存在。在内部,log4net执行相同的检查,因此您不会通过自己进行更改 但正如我所说,在这种情况下,选择A可能是个好主意:
_log.Debug(String.Format("{0} {1} {2}...", param1, param2, param3));
if (_log.IsDebugEnabled())
{
var message = createComplicatedLogMessageThatTakesALotOfTime();
_log.Debug(message);
}
对于所有其他情况,它只是为您记录的每一条消息多添加了三行代码,这是不值得的。之前的分析显示,Log4Net的
IsXXXEnabled
实现并不是最快的,因为它调用了其他几种方法。NLog的版本具有易失性读取功能,因此速度要快得多,但实际上,如果瓶颈在于IsXXXEnabled
,那么您已经在做低延迟的工作,并且可能最终会创建自己的专用日志记录。选项a更好,因为:
您可能不知道Debug()方法背后包装了什么。在传递到log4net的Debug()调用之前,是否有人添加了本地包装器来处理额外的逻辑?log4net在这种方法中做了什么?您可能正在使用log4net的源代码构建程序集,是否有其他团队成员更改了它?好的,您亲自审核了代码,而且速度非常快,您正在使用Nuget的程序集,因此您知道您的团队中没有人更改过它。明天log4net的新版本发布后呢?您怎么知道处理log4net bug的人没有引入一些日志代码,将您的服务器融化在所有紧密的循环中?下一个复制您的代码并对其进行更改的实习生是否和您一样有知识,并且考虑到进行冗长复杂的日志调用的成本可能比预期的更高?另外,请记住,不同的附加器可能有不同的日志成本。如果有人将一个轻量级的快速异步appender更改为一个较慢的同步appender,会发生什么
底线:代码防御。这是一个非常简单和便宜的bool检查,它可以防止在规模和负载下出现一些意外和棘手的性能问题。你会不会看着这张支票说,‘我真的很后悔写了那张支票’?不太可能。你能更具体地描述一下你的“以前的分析”吗?抓取一个反编译器并逐步通过Log4Net的IsXXX启用-你可以跳过许多虚拟方法调用。对于调试,可能是这种情况,但对于其他方法,如log(),在查看了数百行if语句检查之后,然后它开始膨胀代码,变得毫无意义。