记录复杂性和对MessageFormat性能的关注

时间:2009-03-25 07:40:15

标签: java performance logging

我的应用程序使用log4j进行日志记录,通常我通过检查特定级别是否已启用来进行日志记录,然后按以下方式记录

if(Logger.isApplicationDebugEnabled()){
   Logger.logApplicationDebug("something"+values);  
 }

现在,如果检查在jUnit测试期间减少了我们的分支覆盖范围。为了克服这个问题,我的朋友建议删除“if”检查记录。

  1. 我的第一个朋友建议直接删除if check和log。这种方法的问题在于它可能会因为形成字符串而减慢应用程序,而这些字符串无论如何都不会在日志文件中结束。
  2. 我想到的第二种方法与SLF4j非常相似。

    Logger.debug(“数字{0},日期{1,日期}”,1234,新日期());

  3. 这感觉非常有吸引力和简单。(这个解决方案在内部使用MessageFormat.format(str,object [])方法。但是我担心它可能具有的性能。还要注意'Logger'是我的内部实用程序类,在每个日志方法中,都会检查日志启用。 你们有什么建议?我浏览了速度模板,但它需要参数图。是否有任何轻量级解决方案只能替换基于param索引位置的值,或者这个解决方案可以吗?

4 个答案:

答案 0 :(得分:2)

好的,我会问一个显而易见的问题:为什么不在运行单元测试时启用调试日志记录 - 或者所有级别?这样做的好处是可以增加代码覆盖率测试和测试日志记录中的问题(这远远超出可能性范围)。

是否启用了日志记录的检查是有原因的:不仅构建最终日志字符串而且构造各个参数本身可能很昂贵(在大循环内部)。使用MessageFormat或java.util.Formatter或其他任何不会解决第二个问题。我真的鼓励你继续检查。

答案 1 :(得分:2)

我实际上已经完成了你在一个项目上的建议,我对这种方法有积极的经验。我在commons-logging上创建了一个额外的层,允许在MessageFormat下进行消息格式化。

这些是我在测量您描述的几乎相同的使用模式后获得的结果,10000次调用如下:

    for (int i = 0; i < 10000; i ++) {
        log.debug("Example message: {0} from {1} at {2}!", i, "test", new Date());
    }
  

  1. 登录:commons-logging = 664ms,Slf4j = 559ms,MyLog = 3134ms
  2. 注销:commons-logging = 6ms,Slf4j = 7ms,MyLog = 7ms
  3. 显然,调试输出打开时“MyLog”速度相当慢,但是当调试关闭时,它们与它们相当。为了说清楚,在“MyLog”中,我在实际格式化消息之前明确检查了isDebugEnabled()

    但是,生成的日志记录代码现在更加清晰,我们整个团队最终会生成更多有用和详细的消息。在此之前,使用单独的方法构建更长的记录器消息并不罕见。

    鉴于在关闭日志记录时几乎没有额外的性能影响,我可以看到自己将来会使用这种技术。

答案 2 :(得分:0)

要知道的唯一方法是衡量。关于性能的猜测几乎总是错误的:)

就我个人而言,我可能只是坚持使用你原来的log4j代码 - 不要太担心覆盖范围。防止对始终遵循的代码路径进行太多日志调用是合理的 - 但我不会为错误条件等问题而烦恼,因为在这种情况下,您已经处于一种奇怪且极有希望的情况。在其中,编写最易读的代码,然后确保您的应用程序执行得很好。 如果没有,请对其进行分析以找出问题所在。 如果它在日志记录代码中,请对其进行优化。

答案 3 :(得分:0)

我强烈建议使用log4j的slf4j facade,它允许你使用这种语法

log.info(来自{}“的”Hello {},“世界”,“我”)

只有在确定事件应该被记录之后才进行字符串扩展,因此您不必指定ifEnabled包装器。然后使用log4j作为slf4j的后端。

此外,它已经比MessageFormatter更快地

相关问题