dev@glassfish.java.net

Re: a more efficient way to initialize Loggers?

From: Lloyd L Chambers <Lloyd.Chambers_at_Sun.COM>
Date: Thu, 07 Dec 2006 12:51:02 -0800

Frank,

Try the link *after* logging in.

https://glassfish.dev.java.net/issues/show_bug.cgi?id=1687

The Logger code is quite complicated, and has a variety of
synchronization points internally. It's a big job to investigate and
improve it. I don't understand it well enough to say why it is so slow.

In the meantime, initializing a static variable that might never be
used, or might not be used for a relatively long time is a pointless
waste of computing time.

The "other code" could be changed trivially (and for the better) by
changing occurrences of

_logger.log(...);

to:

_getLogger().log(...);

Certainly there are many classes in which a Logger is used almost
immediately, and on an ongoing basis, so such an optimization is not
of any value. I'm suggesting that the remaining classes for which
this is not the case might benefit.

In general, static initialization is handy, but a waste of time if
the static variable is never used.

Lloyd


On Dec 7, 2006, at 12:42 PM, Frank Kieviet wrote:

> Lloyd,
>
> The link you sent doesn't work.
>
> Why is initialization of the loggers so expensive? Isn't it
> possible to
> optimize that instead of forcing other code to change the way that
> they
> use loggers?
>
> Frank
>
>
> -----Original Message-----
> From: Lloyd L Chambers [mailto:Lloyd.Chambers_at_Sun.COM]
> Sent: Thursday, December 07, 2006 10:50
> To: dev_at_glassfish.dev.java.net
> Subject: a more efficient way to initialize Loggers?
>
> 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
> (); }