dev@glassfish.java.net

a more efficient way to initialize Loggers?

From: Lloyd L Chambers <Lloyd.Chambers_at_Sun.COM>
Date: Thu, 07 Dec 2006 10:50:15 -0800

Please see:

https://glassfish.dev.java.net/issues/post_bug.cgi

------------
Initializing all the Loggers at startup
[ServerLogManager.reInitializeServerLoggers] takes about half a
second even on a very fast machine.

But observe that many Loggers are never used unless an exception
needs to be reported. The typical
idiom is: try { ... } catch( ... ) { _logger.log(...); }.

Thus, a cost is paid even if the logger is never used. Additionally,
Loggers cannot be initialized at
startup because the ServerContext is not yet available. This causes
wasted cycles and leads to a
transient half-initialized state which much be protected against
internally.

We might be see some performance improvements by deferring the
initialization of Loggers. This would
need to be done in a thread-safe manner. I think the following code
snippet is thread-safe and would
remain efficient, especially if applied only to cases where the
Logger is needed only for exceptions:


         private static Logger
     getLogger() {
         // if it's non-null, then it's safe to return it
         if ( _logger != null ) {
             return _logger;
         }

         // null, synchronize before getting the logger
         synchronized( StringManagerBase.class ) {
             if ( _logger == null ) {
                 _logger=LogDomains.getLogger(LogDomains.UTIL_LOGGER)
             }
         }
         return _logger;
     }

This could be captured in a class for convenience:


     static private final class LoggerGetter {
         private final String mLoggerName;
         private volatile Logger mLogger;

         public LoggerGetter( final String loggerName ) {
             mLoggerName = loggerName;
             mLogger = null;
         }
             public Logger
         getLogger() {
             // if it's non-null, then it's safe to return it
             if ( mLogger != null ) {
                 return mLogger;
             }
             else synchronized( this ) {
                 if ( mLogger == null ) {
                     mLogger=LogDomains.getLogger
(LogDomains.UTIL_LOGGER)
                 }
             }
             return mLogger;
         }
     }

and used like this:
static private final LoggerGetter _loggerGetter = new LoggerGetter
( "MyLogger" );
static private Logger _getLogger() { return _loggerGetter.getLogger(); }