In log4j, does checking isDebugEnabled before logging improve performance?
Solution 1:
In this particular case, Option 1 is better.
The guard statement (checking isDebugEnabled()
) is there to prevent potentially expensive computation of the log message when it involves invocation of the toString()
methods of various objects and concatenating the results.
In the given example, the log message is a constant string, so letting the logger discard it is just as efficient as checking whether the logger is enabled, and it lowers the complexity of the code because there are fewer branches.
Better yet is to use a more up-to-date logging framework where the log statements take a format specification and a list of arguments to be substituted by the logger—but "lazily," only if the logger is enabled. This is the approach taken by slf4j.
See my answer to a related question for more information, and an example of doing something like this with log4j.
Solution 2:
Since in option 1 the message string is a constant, there is absolutely no gain in wrapping the logging statement with a condition, on the contrary, if the log statement is debug enabled, you will be evaluating twice, once in the isDebugEnabled()
method and once in debug()
method. The cost of invoking isDebugEnabled()
is in the order of 5 to 30 nanoseconds which should be negligible for most practical purposes. Thus, option 2 is not desirable because it pollutes your code and provides no other gain.
Solution 3:
Using the isDebugEnabled()
is reserved for when you're building up log messages by concatenating Strings:
Var myVar = new MyVar();
log.debug("My var is " + myVar + ", value:" + myVar.someCall());
However, in your example there is no speed gain as you're just logging a String and not performing operations such as concatenation. Therefore you're just adding bloat to your code and making it harder to read.
I personally use the Java 1.5 format calls in the String class like this:
Var myVar = new MyVar();
log.debug(String.format("My var is '%s', value: '%s'", myVar, myVar.someCall()));
I doubt there's much optimisation but it's easier to read.
Do note though that most logging APIs offer formatting like this out of the box: slf4j for example provides the following:
logger.debug("My var is {}", myVar);
which is even easier to read.
Solution 4:
In Java 8, you don't have to use isDebugEnabled()
to improve the performance.
https://logging.apache.org/log4j/2.0/manual/api.html#Java_8_lambda_support_for_lazy_logging
import java.util.logging.Logger;
...
Logger.getLogger("hello").info(() -> "Hello " + name);
Solution 5:
As others have mentioned using the guard statement is only really useful if creating the string is a time consuming call. Specific examples of this are when creating the string will trigger some lazy loading.
It is worth noting that this problem can be completed avoided by using Simple Logging Facade for Java or (SLF4J) - http://www.slf4j.org/manual.html . This allows method calls such as:
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
This will only convert the passed in parameters to strings if debug is enabled. SLF4J as its name suggests is only a facade and the logging calls can be passed to log4j.
You could also very easily "roll your own" version of this.
Hope this helps.