在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)
如何检查是否通过宏启用调试使其更高效?
答案 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")
}
这样就不会创建额外的对象;代码就像你明确写出来一样工作,除了你不必实际编写这个样板文件。