Performance scala日志库按值调用与按名称调用的性能
我最近一直在研究各种scala日志库,它们中的绝大多数实现了如下日志功能:Performance scala日志库按值调用与按名称调用的性能,performance,scala,logging,callbyname,Performance,Scala,Logging,Callbyname,我最近一直在研究各种scala日志库,它们中的绝大多数实现了如下日志功能: def debug(s: => String) 因此,如果您关闭了调试日志记录,它将不会执行该语句。然而,我只是偶然发现了其中的一个好处 与许多Scala日志库不同,Logula不使用 其日志语句的按名称传递语义(例如,f:=>A), 这意味着两件事: Scala编译器不必为每个日志语句创建一次性的闭包对象。这将减少垃圾量 收集压力 这对我来说完全有道理。所以我的问题是,是否有任何真实的性能基准/数据来比较这
def debug(s: => String)
因此,如果您关闭了调试日志记录,它将不会执行该语句。然而,我只是偶然发现了其中的一个好处
与许多Scala日志库不同,Logula不使用
其日志语句的按名称传递语义(例如,f:=>A),
这意味着两件事:
- Scala编译器不必为每个日志语句创建一次性的闭包对象。这将减少垃圾量 收集压力
这对我来说完全有道理。所以我的问题是,是否有任何真实的性能基准/数据来比较这两种方法?理想情况下,来自实时项目的东西与人为基准测试的东西相比?哪个更快完全取决于用例。如果您记录的是静态字符串,那么只需传入该常量字符串并忽略它就会更快。否则,如果要创建字符串,则必须至少创建一个对象。函数对象既小又便宜——如果忽略它,最好创建一个函数对象而不是字符串 就我个人而言,我认为这种对权衡的第一原则的理解甚至比使用其中一种的特定应用程序的案例研究更有价值,因为它让您了解为什么要选择其中一种(并且您仍然希望对自己的应用程序进行基准测试)
(注意:创建对象的代价取决于垃圾收集器受到的影响有多大;通常,短生命对象的创建和处理速度大约为每秒108次,这不应该是一个问题,除非是在紧密的内部循环中。如果将日志记录语句放在紧密的内部循环中,我认为有问题(你应该为此编写单元测试。)我会冒险说,当需要进行一些有趣的权衡时,关于权衡的哲学讨论更有用,也就是说,不是在这里
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
%
计算闭包对象。
就我个人而言,我认为这种对权衡的基本原则的理解甚至比特定应用程序的案例研究更有价值。
虽然我完全同意这一原则,但现实可能与你预期的完全不同。这就是为什么我要寻找真正的life案例而不是基准测试,因为任何人都可以编写一个基准测试,使一种方式看起来快上百万倍。这主要是出于我自己的好奇心,因为老实说,什么应用程序才是真正的瓶颈?@falmari-它可能会不同于你的预期,特别是如果你从示例中推理的话。这就是为什么我解释了fs.我同意日志记录不应该成为大多数应用程序的瓶颈。@Falmari嗯……你衡量了所有事情吗?有人发誓要衡量应用程序的每一步,包括队列大小、吞吐量和响应时间。如果你这样做,你不希望日志记录增加总时间。事实上,你希望它成为一个瓶颈同步。很好知道!虽然如果您试图使用外部库的日志方法进行日志记录,可能更难实现省略…但这只是说明您应该在需要的地方使用自己的本地@inline final def debug
包装库调用。