8

我最近一直在研究各种 scala 日志库,其中绝大多数都将日志功能实现为

def debug(s: => String)

因此,如果您关闭了调试日志记录,它将不会执行该语句。但是,我刚刚遇到了logula,它特别指出它的好处之一

与许多 Scala 日志库不同,Logula 的日志语句不使用按名称传递的语义(例如,f: => A),这意味着两件事:

  • Scala 编译器不必为每个日志记录语句创建一次性闭包对象。这应该可以减少垃圾收集的压力。

这对我来说真的很有意义。所以我的问题是,是否有任何现实世界的性能基准/数据比较这两种方法?理想情况下来自现场项目的东西与人为的基准?

4

2 回答 2

8

哪个更快完全取决于用例。如果您正在记录静态字符串,那么只传递该常量字符串并忽略它会更快。否则,如果您要创建字符串,则无论如何都必须创建至少一个对象。函数对象既小又便宜——如果你要忽略它,最好创建一个而不是字符串。

就个人而言,我认为这种对权衡的第一性原理的理解比对可能使用其中一个或另一个的特定应用程序的案例研究更有价值,因为它让您了解为什么要选择一个或另一个(并且您仍然希望对自己的应用程序进行基准测试)。

(注意:创建对象的成本取决于垃圾收集器受到的影响有多大;通常,可以以每秒 10 8个数量级的速度创建和处理短期对象,这不是问题除了在紧密的内部循环中。如果您将日志记录语句放在紧密的内部循环中,我认为有问题。您应该为此编写单元测试。)

于 2012-07-31T16:46:23.430 回答
3

我会冒昧地说,当需要进行一些有趣的权衡时,关于权衡的哲学讨论会更有用,也就是说,不是在这里。

class A {
  var debugging = true
  @inline final def debug(msg: => String) = if (debugging) println(msg)

  def f = { debug("I'm debugging!") ; 5 }
}
% scalac292 -optimise a.scala
% ls -l *.class
-rw-r--r--  1 paulp  staff  1503 Jul 31 22:40 A.class
%

计算闭包对象。

于 2012-08-01T05:44:02.357 回答