In languages like C/C++/Objective-C it's common to use preprocessor macros to define logging mechanisms that are not even compiled for released binaries, thus causing no performance hit. Something along the lines of:
#ifdef DEBUG
printf("some event we want to log\n");
#endif
Now, I know there's no preprocessor in Scala. So my question is: what is the best way to implement a mechanism to log program activity for debug purposes, while impacting performance the least when it's turned off?
Current practice (in Scala 2.9.x or earlier) is to use a thunk type (e.g. see Simple Logging Facade for Scala SLFS):
This is often less expensive than actually constructing the string, since the string creation (and any subsequent activity) is only done if
logging
is true. However, it still incurs the cost of closure creation for the thunkx
above.However, starting from Scala 2.10.x, there is an experimental macro implementation included in the standard distribution (see this page, or SIP). The macro system will allow you to write logging calls which incur almost no runtime cost (other than the
logging
variable check) - they allow you to inline the call tolog
, so that this:becomes:
Notice that in this case there is no closure created for
log
, and the logging message string is only evaluated iflogging
is true - the cost is only the if-check.Log4J is a common JVM logging framework. It is specifically designed to have minimal performance impact:
So when you make a call like:
the framework will first check if "debug" logging is enabled. This check is very fast. If logging is disabled, then it doesn't do any more work.
There is one catch however. If you write
then the framework won't do the debug-enabled check before performing the expensive operation. The way to correct for this is to say:
You can use
scala.annotation.elidable