Typesafe的scala-logging究竟比其他日志框架更具性能?

时间:2017-08-15 19:51:38

标签: scala logging scala-logging

Github页面上显示:

  

它具有高性能,因为感谢Scala宏,应用 check-enabled-idiom 并生成以下代码:

if (logger.isDebugEnabled) logger.debug(s"Some $expensive message!")

比Play的记录更有效率吗?

在Play中,它使用自己的调用包装底层记录器,并检查是否在常规代码中启用了调试,不涉及宏:

def debug(message: => String)(implicit mc: MarkerContext): Unit = {
  if (isDebugEnabled) {
    mc.marker match {
      case None => logger.debug(message)
      case Some(marker) => logger.debug(marker, message)
    }
  }
}

(源代码为here

如何检查是否通过宏启用调试使其更高效?

1 个答案:

答案 0 :(得分:2)

让我们考虑一个更简单的方法:

def debug(message: => String): Unit = {
  if (logger.isDebugEnabled) {
    logger.debug(message)
  }
}

此处,此方法接受by-name参数,并仅在启用调试时调用它。在内部,所有by-name参数都映射到nullary函数,因此该方法等效于以下方法:

def debug(message: () => String): Unit = {
  if (logger.isDebugEnabled) {
    logger.debug(message())
  }
}

这意味着每次在代码中调用此方法时,都会创建新功能实例。也许编译器有时可以优化它,但绝对不是总能。通常,使用带名称调用调用方法需要在内部创建函数类的实例,如果捕获任何变量,几乎总是如此:

logger.debug(s"Something interesting happened: $something. Message: $message")

然后这个函数对象,作为一个闭包,也将包含对这些捕获变量的引用。

与此相比,基于宏的方法将被重写为条件检查和基础记录器调用:

logger.debug(s"Something interesting happened: $something. Message: $message")
// gets rewritten to
if (logger.logger.isDebugEnabled) {
  logger.logger.debug(s"Something interesting happened: $something. Message: $message")
}

这样就不会创建额外的对象;代码就像你明确写出来一样工作,除了你不必实际编写这个样板文件。