dev@glassfish.java.net

Re: a more efficient way to initialize Loggers?

From: Peter Williams <Pete.Williams_at_Sun.COM>
Date: Thu, 07 Dec 2006 11:47:17 -0800

Lloyd L Chambers wrote:
> 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:
>
This is the double checked locking pattern and is NOT thread safe. See
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
for an exhaustive academic analysis if interested.

-Peter
>
> 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(); }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>