Skip to content

Instantly share code, notes, and snippets.

@yegeniy
Created October 13, 2012 16:30
Show Gist options
  • Save yegeniy/3885248 to your computer and use it in GitHub Desktop.
Save yegeniy/3885248 to your computer and use it in GitHub Desktop.
Why does slf4j overload its Logger.debug methods instead of using a single method with varargs?

slf4j's Logger.debug is a perfect example of item 42 in Effective Java 2nd Edition (on varargs), but I have a question.

I believe that they have found that the vast majority of use cases of debug have 2 or less arguments and that by over loading the methods with 0,1,2 arguments, the implementation is able to avoid allocating an array?

  /**
   * Log a message at the DEBUG level.
   *
   * @param msg the message string to be logged
   */
  public void debug(String msg);


  /**
   * Log a message at the DEBUG level according to the specified format
   * and argument.
   * <p/>
   * <p>This form avoids superfluous object creation when the logger
   * is disabled for the DEBUG level. </p>
   *
   * @param format the format string
   * @param arg    the argument
   */
  public void debug(String format, Object arg);


  /**
   * Log a message at the DEBUG level according to the specified format
   * and arguments.
   * <p/>
   * <p>This form avoids superfluous object creation when the logger
   * is disabled for the DEBUG level. </p>
   *
   * @param format the format string
   * @param arg1   the first argument
   * @param arg2   the second argument
   */
  public void debug(String format, Object arg1, Object arg2);

  /**
   * Log a message at the DEBUG level according to the specified format
   * and arguments.
   * <p/>
   * <p>This form avoids superfluous string concatenation when the logger
   * is disabled for the DEBUG level. However, this variant incurs the hidden
   * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method,
   * even if this logger is disabled for DEBUG. The variants taking
   * {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two}
   * arguments exist solely in order to avoid this hidden cost.</p>
   *
   * @param format    the format string
   * @param arguments a list of 3 or more arguments
   */
  public void debug(String format, Object... arguments);

https://github.com/qos-ch/slf4j/blob/master/slf4j-api/src/main/java/org/slf4j/Logger.java#L304-344

=====

However, I'm not really sure that there are actually any savings with this implementation.

Look at SimpleLogger: https://github.com/qos-ch/slf4j/blob/master/slf4j-simple/src/main/java/org/slf4j/impl/SimpleLogger.java#L409-430 https://github.com/qos-ch/slf4j/blob/master/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java#L150

The MessageFormatter.format ends up creating an array with its arrayFormat method, which is always invoked by a regular invokation of SimpleLogger.debug - except in the case of no args since formatting is avoided in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment