6

在 C/C++/Objective-C 等语言中,通常使用预处理器宏来定义甚至不为已发布的二进制文件编译的日志记录机制,因此不会对性能造成影响。类似于以下内容:

#ifdef DEBUG
printf("some event we want to log\n");
#endif

现在,我知道 Scala 中没有预处理器。所以我的问题是:实现一种机制来记录程序活动以进行调试的最佳方式是什么,同时在关闭时对性能的影响最小?

4

3 回答 3

15

您可以使用scala.annotation.elidable

可能在生成的代码中删除调用的方法的注释。

将 -Xelide-below 传递给 scalac 会影响行为。如果给定注释的优先级低于命令行参数,则标记为 elidable 的方法将从生成的代码中省略。例子:

于 2012-08-20T20:04:06.343 回答
5

当前的做法(在 Scala 2.9.x 或更早版本中)是使用 thunk 类型(例如,请参阅 Simple Logging Facade for Scala SLFS):

def log(x: =>Any) = if (logging) println(x)

// later in code
log("var1: " + myVar1)

这通常比实际构造字符串更便宜,因为字符串创建(和任何后续活动)只有在logging为真时才完成。但是,它仍然会产生上述 thunk 的闭包创建成本x

但是,从 Scala 2.10.x 开始,标准发行版中包含了一个实验性宏实现(请参阅此页面SIP)。宏系统将允许您编写几乎不会产生运行时成本的日志调用(除了logging变量检查) - 它们允许您内联对 的调用log,因此:

log("var1: " + myVar1)

变成:

if (logging) log("var1: " + myVar1)

请注意,在这种情况下,没有为 创建闭包log,并且仅在为 true 时才评估日志消息字符串logging- 成本只是 if-check。

于 2012-08-20T19:46:54.897 回答
1

Log4J是一个常见的 JVM 日志框架。它专门设计用于将性能影响降至最低:

在运行 JDK 1.3.1 的时钟频率为 800Mhz 的 AMD Duron 上,确定是否应该记录日志语句需要大约 5 纳秒。实际的日志记录也相当快,从使用 SimpleLayout 的 21 微秒到使用 TTCCLayout 的 37 微秒不等。PatternLayout 的性能几乎与专用布局一样好,只是它更加灵活。

因此,当您拨打以下电话时:

LOG.debug("something here")

框架将首先检查是否启用了“调试”日志记录。这个检查非常快。如果日志记录被禁用,则它不再做任何工作。

然而,有一个问题。如果你写

LOG.debug(expensiveOperation())

那么框架在执行昂贵的操作之前不会进行启用调试的检查。纠正这种情况的方法是:

if(LOG.isDebugEnabled) LOG.debug(expensiveOperation())
于 2012-08-20T19:45:23.220 回答