Also, anything you can speed up with Jandex might also be very useful in 2.0! So let&#39;s definitely take a good look :)<br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Nov 5, 2012 at 11:44 AM, Lincoln Baxter, III <span dir="ltr">&lt;<a href="mailto:lincolnbaxter@gmail.com" target="_blank">lincolnbaxter@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Great!<br><br>Please send a pull request for the ObserverCapture issue! Thanks!<br><br>Good plan with the bootstrap API, and are you sure that Jandex would require changes in Weld-API? Look at what has been done in 2.0 with the <a href="https://github.com/forge/core/blob/2.0/plugin-container/src/main/java/org/jboss/forge/container/modules/ModularWeldDeployment.java" target="_blank">https://github.com/forge/core/blob/2.0/plugin-container/src/main/java/org/jboss/forge/container/modules/ModularWeldDeployment.java</a><br>

<br>What APIs did you have to change?<br><br>Looking forward to seeing your changes!<span class="HOEnZb"><font color="#888888"><br><br>~Lincoln</font></span><div class="HOEnZb"><div class="h5"><br><div class="gmail_extra">
<br><br><div class="gmail_quote">On Mon, Nov 5, 2012 at 2:10 AM, Thomas Frühbeck <span dir="ltr">&lt;<a href="mailto:fruehbeck@aon.at" target="_blank">fruehbeck@aon.at</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <div>The first issue
      (ObserverCaptureExtension.scan) is the easiest and most improving,
      it only needs your approval that it&#39;s really up to the point -
      it&#39;s just a few lines in fact.<br>
      I will provide a proposal in my clone at github and notify you.<br>
      <br>
      The Bootstrap redesign idea I will provide in a seperate branch in
      same repo.<br>
      The Jandex-idea would need also changes in the Weld-API, so they
      are somewhat theoretical :-/<br>
      <br>
      Regards,<br>
      Thomas<br>
      <br>
      Am 05.11.2012 01:27, schrieb Lincoln Baxter, III:<br>
    </div><div><div>
    <blockquote type="cite">I think performance improvements in Forge 1.x are very
      important even now!<br>
      <br>
      It&#39;s going to be around for a very long time and while we are
      working on Forge 2.0 now, the kinds of improvements you are
      talking about, Thomas, are very significant!<br>
      <br>
      How can we help? Do you think you could put this code into a
      branch with a single commit (or just one for each change) so that
      we can see just how much you had to change?<br>
      <br>
      The problem with the weld container is the Hibernate Tools plugin.
      If that one works, and the Openshift and AS7 plugins work, then
      it&#39;s safe to assume that it&#39;s working fine. It was a hack to solve
      a classloading problem, but if we can fix it now, that&#39;s great!<br>
      <br>
      ~Lincoln<br>
      <div class="gmail_extra"><br>
        <br>
        <div class="gmail_quote">On Sat, Nov 3, 2012 at 3:27 PM, George
          Gastaldi <span dir="ltr">&lt;<a href="mailto:ggastald@redhat.com" target="_blank">ggastald@redhat.com</a>&gt;</span>
          wrote:<br>
          <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Thomas,<br>
            <br>
            Nice to know that you&#39;ve found some improvements for Forge
            1.x startup time. However, we are rewriting Forge in 2.x
            from the ground up and we&#39;re focusing on performance and
            flexibility in first place.<br>
            <br>
            We encourage you to try the 2.0 branch and help us on
            finding some possible performance problems if you feel so.<br>
            <br>
            As for now, we are avoiding any major changes and updates to
            1.x.<br>
            <br>
            Best Regards,<br>
            <br>
            George Gastaldi<br>
            <br>
            Em 03/11/2012, às 15:41, Thomas Frühbeck &lt;<a href="mailto:fruehbeck@aon.at" target="_blank">fruehbeck@aon.at</a>&gt;
            escreveu:<br>
            <div>
              <div><br>
                &gt; Hi,<br>
                &gt;<br>
                &gt; following the discussions about boot-up performance
                of Forge I made some<br>
                &gt; investigations using a profiler.<br>
                &gt; After testing a lot of different scenarios I would
                like to share my<br>
                &gt; results and ask for your opinion on it.<br>
                &gt;<br>
                &gt;
*************************************************************************************<br>
                &gt; Issue 1.: hot spot inv.<br>
                &gt;
                org.jboss.forge.bus.cdi.ObserverCaptureExtension.scan<br>
                &gt;     profiling shows that 37% CPU time are used in
                firing<br>
                &gt; ProcessAnnotatedType events, which are AFAICS only
                used to filter old<br>
                &gt; event types<br>
                &gt;     &quot;37,2% - 13.442 ms - 1.866 inv.<br>
                &gt;
                org.jboss.weld.bootstrap.events.ProcessAnnotatedTypeImpl.fire&quot;<br>
                &gt;<br>
                &gt;     By introducing a preparatory check in
                ObserverCaptureExtension like<br>
                &gt;&gt;   if (isMethodsAnnotated(originalType,
                Observes.class)) {<br>
                &gt;&gt;   ....<br>
                &gt;&gt;   }<br>
                &gt;<br>
                &gt; and something like:<br>
                &gt;&gt;  private boolean
                isMethodsAnnotated(AnnotatedType&lt;?&gt; type,
                Class&lt;?<br>
                &gt; extends Annotation&gt; annotation) {<br>
                &gt;&gt;      if
                (type.getClass().isAnnotationPresent(annotation))<br>
                &gt;&gt;         return true;<br>
                &gt;&gt;      for (Method m :
                type.getClass().getMethods()) {<br>
                &gt;&gt;          if (m.isAnnotationPresent(annotation))<br>
                &gt;&gt;              return true;<br>
                &gt;&gt;          for (Annotation[] arr :
                m.getParameterAnnotations()) {<br>
                &gt;&gt;             for (Annotation a : arr) {<br>
                &gt;&gt;                 if (a.equals(annotation))<br>
                &gt;&gt;                     return true;<br>
                &gt;&gt;             }<br>
                &gt;&gt;          }<br>
                &gt;&gt;      }<br>
                &gt;&gt;      return false;<br>
                &gt;&gt;  }<br>
                &gt;<br>
                &gt;     we could reduce startup by 20%<br>
                &gt;     &quot;13,8% - 2.438 ms - 1.798 inv.<br>
                &gt;
                org.jboss.weld.bootstrap.events.ProcessAnnotatedTypeImpl.fire<br>
                &gt;<br>
                &gt; Test: call Forge with commands &quot;list-plugins&quot; and
                &quot;exit&quot;, like ~&gt; time<br>
                &gt; ((echo forge list-plugins; echo exit;)| bin/forge)<br>
                &gt;<br>
                &gt; Before optimization:<br>
                &gt; ~/forge&gt; time ((echo forge list-plugins
                &amp;&amp; echo exit)| bin/forge )<br>
                &gt;     _____<br>
                &gt;    |  ___|__  _ __ __ _  ___<br>
                &gt;    | |_ / _ \| `__/ _` |/ _ \  \\<br>
                &gt;    |  _| (_) | | | (_| |  __/  //<br>
                &gt;    |_|  \___/|_|  \__, |\___|<br>
                &gt;                    |___/<br>
                &gt;<br>
                &gt; [no project] forge-distribution-1.1.1-SNAPSHOT $
                forge list-plugins<br>
                &gt;
org.richfaces.forge.richfaces-forge-plugin:1.0.5.Final:1.0.0-SNAPSHOT-b1a6ebed-462f-40e1-ac08-82f927489301<br>
                &gt;
com.ocpsoft.forge.prettyfaces-plugin:1.0.2.Final:1.0.0-SNAPSHOT-c6b071ad-a6df-4112-8fff-82ecccd003fb<br>
                &gt;
org.jboss.hibernate.forge.hibernate-tools-plugin:1.0.5.Final:1.0.0-SNAPSHOT-afb1da29-a99f-4dd7-b020-5f3ba6073cde<br>
                &gt;
org.arquillian.forge.arquillian-plugin:1.0.3-SNAPSHOT:1.0.0-SNAPSHOT-42907982-d02e-4a1d-8ea5-8e66c8013fde<br>
                &gt; [no project] forge-distribution-1.1.1-SNAPSHOT $
                exit<br>
                &gt;<br>
                &gt;<br>
                &gt; real    0m9.721s<br>
                &gt; user    0m26.533s<br>
                &gt; sys     0m0.433s<br>
                &gt;<br>
                &gt; After optimization:<br>
                &gt; ~forge1.1.1-weld1.2&gt; time ((echo forge
                list-plugins; echo exit;)| bin/forge)<br>
                &gt; Using Forge at
                /raid/home/thomas/java/forge1.1.1-weld1.2<br>
                &gt;     _____<br>
                &gt;    |  ___|__  _ __ __ _  ___<br>
                &gt;    | |_ / _ \| `__/ _` |/ _ \  \\<br>
                &gt;    |  _| (_) | | | (_| |  __/  //<br>
                &gt;    |_|  \___/|_|  \__, |\___|<br>
                &gt;                    |___/<br>
                &gt;<br>
                &gt; [no project] forge1.1.1-weld1.2 $ forge
                list-plugins<br>
                &gt;
org.richfaces.forge.richfaces-forge-plugin:1.0.5.Final:1.0.0-SNAPSHOT-b1a6ebed-462f-40e1-ac08-82f927489301<br>
                &gt;
com.ocpsoft.forge.prettyfaces-plugin:1.0.2.Final:1.0.0-SNAPSHOT-c6b071ad-a6df-4112-8fff-82ecccd003fb<br>
                &gt;
org.jboss.hibernate.forge.hibernate-tools-plugin:1.0.5.Final:1.0.0-SNAPSHOT-afb1da29-a99f-4dd7-b020-5f3ba6073cde<br>
                &gt;
org.arquillian.forge.arquillian-plugin:1.0.3-SNAPSHOT:1.0.0-SNAPSHOT-42907982-d02e-4a1d-8ea5-8e66c8013fde<br>
                &gt; [no project] forge1.1.1-weld1.2 $ exit<br>
                &gt;<br>
                &gt;<br>
                &gt; real    0m6.016s<br>
                &gt; user    0m14.482s<br>
                &gt; sys     0m0.449s<br>
                &gt;<br>
                &gt;<br>
                &gt;
*************************************************************************************<br>
                &gt; Issue 2.: double starting of Weld container<br>
                &gt; I admit that I do not fully understand, what I did
                and if this really<br>
                &gt; provides the full solution, but it worked and
                produced a fully<br>
                &gt; functional Forge instance.<br>
                &gt;<br>
                &gt; I tried to restructure the Bootstrap logic a bit:<br>
                &gt;<br>
                &gt;                initializeClassloader();<br>
                &gt;                WeldContainer container =
                weld.initialize();<br>
                &gt;                manager =
                container.getBeanManager();<br>
                &gt;<br>
                &gt;                try<br>
                &gt;                {<br>
                &gt;                   loadPlugins();<br>
                &gt;                   weld.reInitialize();<br>
                &gt;<br>
                &gt; where initializeClassloader already uses the
                CompositeClassloader:<br>
                &gt;<br>
                &gt;    private static void initializeClassloader() {<br>
                &gt;        ModuleLoader moduleLoader =
                Module.getBootModuleLoader();<br>
                &gt;<br>
                &gt;        CompositeClassLoader composite = new
                CompositeClassLoader();<br>
                &gt;
                composite.add(Module.forClassLoader(Bootstrap.class.getClassLoader(),<br>
                &gt; true).getClassLoader());<br>
                &gt;<br>
                &gt;      
                 Thread.currentThread().setContextClassLoader(composite);<br>
                &gt;    }<br>
                &gt;<br>
                &gt; and loadPlugins simply adds more classloaders:<br>
                &gt;<br>
                &gt;          CompositeClassLoader composite =<br>
                &gt;
                (CompositeClassLoader)Thread.currentThread().getContextClassLoader();<br>
                &gt;          for (PluginEntry plugin : toLoad)<br>
                &gt;          {<br>
                &gt;                Module module =<br>
                &gt;
moduleLoader.loadModule(ModuleIdentifier.fromString(plugin.toModuleId()));<br>
                &gt;              
                 composite.add(module.getClassLoader());<br>
                &gt;<br>
                &gt;<br>
                &gt; This way the classes are already available in the
                correct classloader<br>
                &gt; for the later ModularWeld.reInitialize():<br>
                &gt;<br>
                &gt;     public void reInitialize() {<br>
                &gt;         bootstrap.revisit();<br>
                &gt;         bootstrap.validateBeans();<br>
                &gt;         bootstrap.endInitialization();<br>
                &gt;     }<br>
                &gt;<br>
                &gt; Where Bootstrap.revisit simply revisits the
                BeanDeployments which have<br>
                &gt; been newly found:<br>
                &gt;<br>
                &gt;     private static class DeploymentVisitor {<br>
                &gt; .....<br>
                &gt;         public Map&lt;BeanDeploymentArchive,
                BeanDeployment&gt; revisit() {<br>
                &gt;             for (BeanDeploymentArchive archvive :<br>
                &gt; deployment.getBeanDeploymentArchives()) {<br>
                &gt;                 if<br>
                &gt;
                (!managerAwareBeanDeploymentArchives.containsKey(archvive))
                {<br>
                &gt;                     visit(archvive,
                managerAwareBeanDeploymentArchives,<br>
                &gt; new HashSet&lt;BeanDeploymentArchive&gt;(), true);<br>
                &gt;                     BeanDeployment bd =<br>
                &gt; managerAwareBeanDeploymentArchives.get(archvive);<br>
                &gt;                     bd.createBeans(environment);<br>
                &gt;                     bd.deployBeans(environment);<br>
                &gt;                 }<br>
                &gt;             }<br>
                &gt;             return
                managerAwareBeanDeploymentArchives;<br>
                &gt;         }<br>
                &gt;<br>
                &gt;<br>
                &gt;
*************************************************************************************<br>
                &gt; Issue 3.: invocation of potentially expensive
                operations on<br>
                &gt; non-annotated or annotation-relevant classes<br>
                &gt; The current BeanDeployer simply invokes
                ProcessAnnotatedType on any<br>
                &gt; class, w/o checking, if this class is used by any
                annotation anywhere.<br>
                &gt; By jandexing all jars and assembling the dispersed
                Jandex indices during<br>
                &gt; URLScanning we could reduce the expensive WeldClass
                conversion.<br>
                &gt;<br>
                &gt; Original:<br>
                &gt;     11.108 ms - 2.024 inv.
                org.jboss.weld.bootstrap.BeanDeployer.addClass<br>
                &gt; Jandex-aware:<br>
                &gt;     4.721 ms - 990 inv.
                org.jboss.weld.bootstrap.BeanDeployer.addClass<br>
                &gt;<br>
                &gt; Possible solution:<br>
                &gt;     - 1. URLHandler scans Jandex file locations<br>
                &gt;<br>
                &gt;     protected void addToDiscovered(String name, URL
                url) {<br>
                &gt; ...<br>
                &gt;         } else if (name.endsWith(JANDEX_IDX)) {<br>
                &gt;             discoveredJandexIndexUrls.add(url);<br>
                &gt;         }<br>
                &gt;     }<br>
                &gt;<br>
                &gt;     - 2. URLScanner assembles all found Jandex
                indices:<br>
                &gt;<br>
                &gt;         List&lt;Index&gt; jandexIndexes = new
                ArrayList&lt;Index&gt;();<br>
                &gt;         for (URL jandexUrl :
                handler.getDiscoveredJandexIndexUrls()) {<br>
                &gt;                 jandexIndexes.add(new<br>
                &gt; IndexReader(jandexUrl.openStream()).read());<br>
                &gt;         }<br>
                &gt;<br>
                &gt;     - 3. BeanDeployer does expensive WeldClass
                loading only if class is<br>
                &gt; mentioned in the Jandex indices<br>
                &gt;     - 3.a. first collapse the Jandex-indices to a
                simple list of class<br>
                &gt; names:<br>
                &gt;         for (Index jandexIndex : jandexIndexes) {<br>
                &gt;             for (List&lt;AnnotationInstance&gt;
                aiList :<br>
                &gt; jandexIndex.getAnnotations().values()) {<br>
                &gt;                 for (AnnotationInstance ai :
                aiList) {<br>
                &gt;                     AnnotationTarget at =
                ai.target();<br>
                &gt;                     if (at instanceof ClassInfo) {<br>
                &gt;
                jandexAnnotated.add(((ClassInfo)at).name().toString());<br>
                &gt;                     } else if (at instanceof
                MethodInfo) {<br>
                &gt;
jandexAnnotated.add(((MethodInfo)at).declaringClass().name().toString());<br>
                &gt;                     } else if (at instanceof
                MethodParameterInfo) {<br>
                &gt;
jandexAnnotated.add(((MethodParameterInfo)at).method().declaringClass().name().toString());<br>
                &gt;                     } else if (at instanceof
                FieldInfo) {<br>
                &gt;
                jandexAnnotated.add(((FieldInfo)at).declaringClass().name().toString());<br>
                &gt;                     }<br>
                &gt;                 }<br>
                &gt;             }<br>
                &gt;         }<br>
                &gt;<br>
                &gt;     - 3.b. query the aggregated list of
                Jandex-aware classes<br>
                &gt;<br>
                &gt;     public BeanDeployer addClass(String className)
                {<br>
                &gt;         Class&lt;?&gt; clazz =
                loadClass(className);<br>
                &gt;         if (clazz != null &amp;&amp;
                isBeanCandidate(clazz) &amp;&amp;<br>
                &gt; jandexContains(className)) {<br>
                &gt;             WeldClass&lt;?&gt; weldClass =
                loadWeldClass(clazz);<br>
                &gt;<br>
                &gt;<br>
                &gt; Yet unsolved issue is the question, wheter an index
                is found in the<br>
                &gt; corresponding Archive or not, so not to enforce
                Jandexing _all_ jars for<br>
                &gt; Forge.<br>
                &gt; Jandexing is very easy though: jandex -m
                &lt;jar&gt;<br>
                &gt;<br>
                &gt; The abovementioned solutions have been implemented
                and produced a<br>
                &gt; functional and correctly working Forge instance.<br>
                &gt; AFAICS the solution for issue 2 could be a means to
                solve the reloading<br>
                &gt; of plugins too, but I didn&#39;t implement and verify
                this.<br>
                &gt;<br>
                &gt; The sources are not available online, because the
                current implementation<br>
                &gt; is highly fragile and not safe for simple usage -
                too many changes in<br>
                &gt; APIs, dependencies, etc.<br>
                &gt;<br>
                &gt; Comments welcome!<br>
                &gt;<br>
                &gt; Regards,<br>
                &gt; Thomas<br>
                &gt;<br>
                &gt; _______________________________________________<br>
                &gt; forge-dev mailing list<br>
                &gt; <a href="mailto:forge-dev@lists.jboss.org" target="_blank">forge-dev@lists.jboss.org</a><br>
                &gt; <a href="https://lists.jboss.org/mailman/listinfo/forge-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/forge-dev</a><br>
                <br>
                _______________________________________________<br>
                forge-dev mailing list<br>
                <a href="mailto:forge-dev@lists.jboss.org" target="_blank">forge-dev@lists.jboss.org</a><br>
                <a href="https://lists.jboss.org/mailman/listinfo/forge-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/forge-dev</a><br>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
        <br clear="all">
        <br>
        -- <br>
        Lincoln Baxter, III<br>
        <a href="http://ocpsoft.org" target="_blank">http://ocpsoft.org</a><br>
        &quot;Simpler is better.&quot;<br>
      </div>
      <br>
      <fieldset></fieldset>
      <br>
      <pre>_______________________________________________
forge-dev mailing list
<a href="mailto:forge-dev@lists.jboss.org" target="_blank">forge-dev@lists.jboss.org</a>
<a href="https://lists.jboss.org/mailman/listinfo/forge-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/forge-dev</a>
</pre>
    </blockquote>
    <br>
  </div></div></div>

<br>_______________________________________________<br>
forge-dev mailing list<br>
<a href="mailto:forge-dev@lists.jboss.org" target="_blank">forge-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/forge-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/forge-dev</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Lincoln Baxter, III<br><a href="http://ocpsoft.org" target="_blank">http://ocpsoft.org</a><br>&quot;Simpler is better.&quot;<br>
</div>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Lincoln Baxter, III<br><a href="http://ocpsoft.org" target="_blank">http://ocpsoft.org</a><br>&quot;Simpler is better.&quot;<br>
</div>