scala日志库中的性能按值调用vs按名称调用

时间:2012-07-31 16:37:33

标签: performance scala logging callbyname

我最近一直在查看各种scala日志库,其中绝大多数都实现了日志记录功能

def debug(s: => String)

因此,如果关闭调试日志记录,则不会执行该语句。但是,我刚刚遇到logula,其中明确指出了其中一项好处

  

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

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

这对我来说真的很有意义。所以我的问题是,是否存在比较这两种方法的真实世界性能基准/数据?理想情况下,从现场项目到人为的基准测试?

2 个答案:

答案 0 :(得分:8)

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

就我个人而言,我认为这种对权衡的第一原则理解甚至比对某个特定应用程序的案例研究更有价值,因为它可以让您理解为什么选择其中一个或者其他(你仍然总是希望对自己的应用程序进行基准测试)。

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

答案 1 :(得分: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
%

计算闭包对象。