Logger statements are among the most heavily used statements in most Java applications. While the code contains Logger statement at different levels, the common practice is to set a default log level for the entire application. This will ensure that only important statements are logged by default.

The general understanding is that the statements below the default log level will not be executed and hence there is no impact to performance. This understanding may not always be true. Let us look at a simple example to understand this specific performance impact:

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created with IntelliJ IDEA.
 * User: sriram
 * Date: 7/2/13
 * Time: 9:59 PM
 * To change this template use File | Settings | File Templates.
 */
public class LoggerTest {

    private static Logger logger = Logger.getLogger("LoggerTest");
    public static void main(String args[])
    {
            // set the default log level to INFO
            logger.setLevel(Level.INFO);

            long startTime = System.nanoTime();
            logger.finer(getLogMessage());    // This should not print anything
            long endTime = System.nanoTime();
            System.out.println("Time for Logger without Boolean check: "+(endTime - startTime));

            startTime = System.nanoTime();
            if (false)
            {
                    logger.finer(getLogMessage());
            }
            endTime = System.nanoTime();
            System.out.println("Time for Logger with Boolean check: "+(endTime - startTime));
    }

    private static String getLogMessage()
    {
            return "Lets understand the "+"performance impact of Java Logger.";
    }
}

Running the above program shows the following output:

Time for Logger without Boolean check: 13440 ns
Time for Logger with Boolean check: 640 ns

As you can see, even though the finer methods did not print anything, the amount of time taken by the first finer __method is much larger than the second one. What is the reason?

According to Java Language Specification (section 15.12.4) arguments to a method are evaluated before the control is transferred to the method itself. Applying this logic to our example above, we can see that getLogMessage() which is the argument of the first finer method is invoked first and then the concatenated string is passed to the finer method. Even though the finer method eventually will not print any thing, the String concatenation operation would have taken place. This is the reason for high execution time for the first finer method._

_

The second finer method is enclosed inside a if-block (with false condition), so the second finer  method is never invoked. Hence the execution time is very low.

Things to keep in mind for Logger statements

  1. Especially at low log levels (finer, finest in Java Logger, debug in Log4J) developers tend to print entire objects, lists and hashmaps. This will incur serious penalty if not coded wisely.
  2. Many new Logger APIs  (SL4J, Logback) support string substitution which can reduce String concatenation problems.
  3. Use Logger statements judiciously in loops. Add additional checks for log levels.
  4. Use standardized string while logging common statements. Most log statements usually have a constant string prefix. By consistently using standardized strings, you can take advantage of Java String caching.

Conclusion

We have looked at a very simple example of the performance impact of Logger statements. In large mission critical applications even simple steps to minimize performance impact will help the end user experience. And logging is no exception to this rule.