I've been looking at the various scala logging libraries lately, and the vast majority of them implement their logging functions as
def debug(s: => String)
So that if you have debug logging turned off, it won't execute the statement. However, I just came across logula which specifically states as one of its benefits
Unlike a lot of Scala logging libraries, Logula doesn't use pass-by-name semantics (e.g., f: => A) for its logging statements, which means two things:
- The Scala compiler doesn't have to create one-off closure objects for each logging statement. This should reduce the amount of garbage collection pressure.
Which actually makes total sense to me. So my question is, is there any real world performance benchmarks/data comparing the 2 approaches? Ideally something from a live project versus contrived benchmarks?
Which is faster depends entirely upon use cases. If you are logging static strings, then it's faster to just pass that constant string in and ignore it. Otherwise, if you're creating strings you have to create at least one object anyway. Function objects are tiny and cheap--you're better off creating one of those than the string if you're going to ignore it.
Personally, I think this sort of first-principles understanding of the tradeoffs is even more valuable than a case study of a particular application that may have used one or the other, because it lets you understand why you would choose one or the other (and you'll still always want to benchmark your own application).
(Note: how expensive object creation is depends on how heavily impacted the garbage collector is; generally, short-lived objects can be created and disposed of at a rate of on the order of 108 per second, which shouldn't be a concern except in tight inner loops. If you're putting logging statements in tight inner loops, I think something is wrong. You should be writing unit tests for that instead.)