5 Replies Latest reply on Feb 18, 2010 12:41 PM by kabirkhan

    Profiling the kernel project

    kabirkhan

      Running a very simple benchmark for deploying a 1000 beans of type Object with no dependencies or configured properties, i.e.

       

         protected List<BeanMetaData> setupContexts()
         {
            List<BeanMetaData> beans = new ArrayList<BeanMetaData>(iterations);
            for (int i = 0 ; i < iterations ; i++)
            {
               BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder("Bean" + i, Object.class.getName());
               beans.add(builder.getBeanMetaData());
            }
            return beans;
         }
      

       

      shows 85% of this time to be spent in the PreInstallAction. A similar test deploying 500 beans with dependencies in the wrong order (which we know from http://community.jboss.org/message/525809#525809 is very slow) shows 25% of the time spent in PreInstallAction.

       

      Most of the time spent in PreInstallAction comes down to adding to and reading from the BasicMetaDataRepository.retrievals map, which hits  UnmodifiableScopeKey.equals lots of times (~2M times in the 1000 beans case):

         public boolean equals(Object object)
         {
            if (object == this)
               return true;
            if (object == null || object instanceof ScopeKey == false)
               return false;
            ScopeKey other = (ScopeKey) object;
            Scope[] otherArray = other.getArray();
            return Arrays.equals(theScopes, otherArray);
         }
      
      I will dig into this tomorrow and see if this can be optimized somehow, and if it is a problem in MDR I'll open another thread for that.
        • 1. Re: Profiling the kernel project
          smarlow

          Last summer, we improved ScopeKey and introduced ScopeKey.getOptimizedKey() (which returns a UnmodifiableScopeKey).  Some background is also on the forums here http://community.jboss.org/thread/96979?start=15&tstart=1

           

          Anyway, we switched to UnmodifiableScopeKey in some places and still use the mutable ScopeKey in others.  UnmodifiableScopeKey.equals performs faster when passed an UnmodifiableScopeKey, however there are still places that pass a mutable ScopeKey.

           

          One way to quickly find/fix the different code sites that call UnmodifiableScopeKey.equals with a mutable ScopeKey, would be to instrument UnmodifiableScopeKey.equals() to call Thread.dumpStack() whenever the mixed case is hit (so you know which caller to fix).  Or you could set a debugger breakpoint.  Eliminating the mixed class type calls to equals should help (see timing later in above thread).

           

          Further changes to improve ScopeKey and UnmodifiableScopeKey are of course welcome.

          • 2. Re: Profiling the kernel project
            kabirkhan

            Thanks, I vaguely remembered that thread and was going to look for it in the morning. I've not yet looked at ScopeKey internals at all beyond what JProfiler tells me, I will do so tomorrow. Anyway, a lot of the overhead seems to be that the ScopeKey.toArray() call ends up calling Collection.toArray() every time. I am guessing it should be possible to cache the array somehow and invalidate as the scopes set is modified, but need to look at the usage first.

            • 3. Re: Profiling the kernel project
              kabirkhan
              ScopeKey discussion continues here: http://community.jboss.org/message/526003#526003
              • 4. Re: Profiling the kernel project
                kabirkhan

                A few other threads that have given some good results

                 

                Optimizing ControllerState: http://community.jboss.org/message/526380#526380

                AnnotatedElementMetaDataLoader component metadata optimization: http://community.jboss.org/message/526629#526629

                • 5. Re: Profiling the kernel project
                  kabirkhan

                  Changing CommonAnnotationAdapter to not always create iterators improves things a little bit:

                   

                  e.g. things like

                   

                         ClassInfo classInfo = info.getClassInfo();
                  -      for (Annotation annotation : retrieval.getAnnotations())
                  +      Annotation[] anns = retrieval.getAnnotations();
                  +      for (int i = 0 ; i < anns.length ; i++)
                         {
                  -         for(T plugin : getPlugins(ElementType.TYPE, annotation, null, annotationClasses))
                  +         for(T plugin : getPlugins(ElementType.TYPE, anns[i], null, annotationClasses))
                            {
                               if (isApplyPhase)
                  -               applyPlugin(plugin, annotation, classInfo, retrieval, handle);
                  +               applyPlugin(plugin, anns[i], classInfo, retrieval, handle);
                               else
                  -               cleanPlugin(plugin, annotation, classInfo, retrieval, handle);
                  +               cleanPlugin(plugin, anns[i], classInfo, retrieval, handle);
                            }
                         }