admin@glassfish.java.net

CODE REVIEW: LifecycleModuleService threaded startup (but #1975)

From: Lloyd L Chambers <Lloyd.Chambers_at_Sun.COM>
Date: Tue, 16 Jan 2007 11:53:30 -0800

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

This change offers a reduction of 6% in startup time on my MacBook
Pro Core 2 Duo 2.33GHz. It works by running the onInitialization work
in a separate thread. No change in load order or initialization is
made with respect to modules.

I also need a volunteer to run QuickLook enterprise on Linux. I will
run it on Mac OS X and Solaris.

The modified file is attached, and diffs are found below.

---------------




-----------------
cvs server: Diffing src/java/com/sun/appserv/server
Index: src/java/com/sun/appserv/server/LifecycleModuleService.java
===================================================================
RCS file: /cvs/glassfish/appserv-core/src/java/com/sun/appserv/server/
LifecycleModuleService.java,v
retrieving revision 1.7
diff -u -w -r1.7 LifecycleModuleService.java
--- src/java/com/sun/appserv/server/LifecycleModuleService.java 1 Dec
2006 09:55:32 -0000 1.7
+++ src/java/com/sun/appserv/server/LifecycleModuleService.java 16
Jan 2007 19:49:06 -0000
@@ -25,6 +25,7 @@
import java.util.HashSet;
import java.util.Set;
+import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
@@ -47,6 +48,10 @@
import com.sun.enterprise.server.ServerContext;
+import com.sun.appserv.management.util.misc.TimingDelta;
+import com.sun.appserv.management.util.misc.RunnableBase;
+import com.sun.appserv.management.helper.AMXDebugHelper;
+
/**
   * Support class to assist in firing LifecycleEvent notifications to
   * registered LifecycleListeners.
@@ -57,30 +62,38 @@
public class LifecycleModuleService implements ServerLifecycle {
+ private OneTimeIniter mOneTimeIniter;
+
+ private final AMXDebugHelper mDebug = new AMXDebugHelper
( "LifecycleModuleService" );
+ private void debug( final Object...args ) { mDebug.println
( args ); }
+
      /**
       * The set of registered LifecycleListeners for event
notifications.
       */
- private ArrayList listeners = new ArrayList();
+ private final List<ServerLifecycleModule> listeners = new
ArrayList<ServerLifecycleModule>();

+ private final class OneTimeIniter extends RunnableBase {
+ private final ServerContext mServerContext;
- public synchronized void onInitialization(ServerContext context)
- throws
ServerLifecycleException {
+ public OneTimeIniter( final ServerContext serverContext ) {
+ mServerContext = serverContext;
+ }
- try {
+ protected void doRun() throws ConfigException,
ServerLifecycleException {
              //ROB: config changes
              //Applications apps =
- //ServerBeansFactory.getServerBean
(context.getConfigContext()).getApplications();
- Applications apps =
ServerBeansFactory.getApplicationsBean(context.getConfigContext());
+ //ServerBeansFactory.getServerBean
(mServerContext.getConfigContext()).getApplications();
+ final Applications apps =
ServerBeansFactory.getApplicationsBean(mServerContext.getConfigContext
());
              if (apps == null) return;
- LifecycleModule[] lcms = apps.getLifecycleModule();
+ final LifecycleModule[] lcms = apps.getLifecycleModule();
              if(lcms == null) return;
- HashSet listenerSet = new HashSet();
+ final HashSet listenerSet = new HashSet();
              for(int i=0;i<lcms.length;i++) {
- LifecycleModule next = lcms[i];
+ final LifecycleModule next = lcms[i];

- if ( isEnabled(next, context.getConfigContext()) ) {
+ if ( isEnabled(next, mServerContext.getConfigContext
()) ) {
                      int order = Integer.MAX_VALUE;
                      String strOrder = next.getLoadOrder();
                      if (strOrder != null) {
@@ -90,14 +103,13 @@
                              nfe.printStackTrace();
                          }
                      }
- ServerLifecycleModule slcm =
- new ServerLifecycleModule(context,
- next.getName(), next.getClassName
());
+ final ServerLifecycleModule slcm =
+ new ServerLifecycleModule(mServerContext,
next.getName(), next.getClassName());
                      slcm.setLoadOrder(order);
                      slcm.setClasspath(next.getClasspath());
                      slcm.setIsFatal(next.isIsFailureFatal());

- ElementProperty[] s = next.getElementProperty();
+ final ElementProperty[] s =
next.getElementProperty();
                      if(s != null) {
                          for(int j=0;j< s.length;j++) {
                              ElementProperty next1 = s[j];
@@ -105,17 +117,57 @@
                          }
                      }
- LifecycleListener listener =
slcm.loadServerLifecycle();
+ final LifecycleListener listener =
slcm.loadServerLifecycle();
                      listenerSet.add(slcm);
                  }
              }
              sortModules(listenerSet);
- } catch(Exception ce1) {
- // FIXME eat it?
- ce1.printStackTrace();
+
+ initialize(mServerContext);
+ }
+ };
+
+
+ private void sortModules( final HashSet listenerSet) {
+ // FIXME: use a better sorting algo
+ for( final Iterator iter = listenerSet.iterator();
iter.hasNext();) {
+ final ServerLifecycleModule next =
(ServerLifecycleModule) iter.next();
+ final int order = next.getLoadOrder();
+ int i=0;
+ for(;i<this.listeners.size();i++) {
+ if( listeners.get(i).getLoadOrder() > order) {
+ break;
+ }
+ }
+ this.listeners.add(i,next);
          }
+ }
+
+ private void initialize( final ServerContext context)
+ throws ServerLifecycleException {
+ if (listeners.isEmpty())
+ return;
- initialize(context);
+ final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
+ for( final ServerLifecycleModule next : listeners ) {
+ next.onInitialization(context);
+ }
+ // set it back
+ resetClassLoader(cl);
+ }
+
+
+
+ public LifecycleModuleService() {
+ }
+
+
+ public synchronized void onInitialization( final ServerContext
context)
+ throws
ServerLifecycleException {
+ mOneTimeIniter = new OneTimeIniter( context );
+
+ mOneTimeIniter.submit( RunnableBase.SUBMIT_ASYNC );
+ // leave it running; we'll sync up with it in start()
      }
      /**
@@ -128,7 +180,6 @@
       * @return true if life cycle module is enabled
       */
      private boolean isEnabled(LifecycleModule lcm, ConfigContext
config) {
-
          try {
              // return false if arguments are null
              if (lcm == null || config == null) {
@@ -136,8 +187,8 @@
              }
              // find the ref to the life cycle module
- Server server = ServerBeansFactory.getServerBean(config);
- ApplicationRef appRef=server.getApplicationRefByRef
(lcm.getName());
+ final Server server = ServerBeansFactory.getServerBean
(config);
+ final ApplicationRef appRef=server.getApplicationRefByRef
(lcm.getName());
              // true if enabled in both lifecyle module and in the ref
              return ((lcm.isEnabled()) &&
@@ -159,46 +210,18 @@
              }
          );
      }
-
- private void sortModules(HashSet listenerSet) {
- // FIXME: use a better sorting algo
- for(Iterator iter = listenerSet.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
- int order = next.getLoadOrder();
- int i=0;
- for(;i<this.listeners.size();i++) {
- if(((ServerLifecycleModule)listeners.get
(i)).getLoadOrder() > order) {
- break;
- }
- }
- this.listeners.add(i,next);
- }
- }
-
- private void initialize(ServerContext context)
- throws ServerLifecycleException {
-
- if (listeners.isEmpty())
- return;
-
- final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
- for(Iterator iter = listeners.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
- next.onInitialization(context);
- }
- // set it back
- resetClassLoader(cl);
- }
-
      public void onStartup(ServerContext context) throws
ServerLifecycleException {
+ final TimingDelta delta = new TimingDelta();
+ // wait for initialization to finish
+ mOneTimeIniter.waitDoneThrow();
+ debug( "Millis for initer to run: ",
(mOneTimeIniter.getNanosFromSubmit() / (1000*1000)), ", wait time =
", delta.elapsedMillis() );
+ mOneTimeIniter = null;
          if (listeners.isEmpty())
              return;
          final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
- for(Iterator iter = listeners.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
-
+ for( final ServerLifecycleModule next : listeners ) {
              // the SERVLET invocation context so J2EE invocations from
              // lifecycle modules get a legal ComponentInvocation.
@@ -222,8 +245,7 @@
              return;
          final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
- for(Iterator iter = listeners.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
+ for( final ServerLifecycleModule next : listeners ) {
              next.onReady(context);
          }
          // set it back
@@ -236,8 +258,7 @@
              return;
          final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
- for(Iterator iter = listeners.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
+ for( final ServerLifecycleModule next : listeners ) {
              next.onShutdown();
          }
          // set it back
@@ -249,12 +270,16 @@
          if (listeners.isEmpty())
              return;
- ClassLoader cl = Thread.currentThread().getContextClassLoader
();
- for(Iterator iter = listeners.iterator(); iter.hasNext();) {
- ServerLifecycleModule next = (ServerLifecycleModule)
iter.next();
+ final ClassLoader cl = Thread.currentThread
().getContextClassLoader();
+ for( final ServerLifecycleModule next : listeners ) {
              next.onTermination();
          }
          // set it back
          resetClassLoader(cl);
      }
}
+