3 Replies Latest reply on Aug 26, 2009 1:42 AM by vivek_saini07

    JBoss portal performance: (Portal)templatePortal.copy(dashbo



      Hi All,
      We are using JBoss portal 2.7.2 and have replaced its portal-core-lib.jar with the latest Fixes from portal SVN.

      Using the SVN fix worked for following method call

      dashboardContext.getPortal(userId)


      We are now facing issue with call to
      (Portal)templatePortal.copy(dashboardContext, userId, false);
      

      The above is called from CustomizationManagerService, MBean when a user access his dashboard for the first time. Invocation of this method results in firing select statements corresponding to each entry in JBP_OBJECT_NODE table. This problem will become issue as soon number of users(12000 users, each with 4-5 pages on dashboard and each page with 4-5 windows) with dashboard increase.

      Do we have a fix for this as of now?
      I am working on work around for this. If some one already have a fix for this, please let me know.

      Thanks
      Vineet

        • 1. Re: JBoss portal performance: (Portal)templatePortal.copy(da

          This is a performance issue with JBP. This particular method gets called when dashboard gets created first time for user.

          If we have 20K users for JBP, 20k select queries gets fired every time a new dashboard gets created. So it appears complete show stopper. Even second level caching does not help in this scenario.

          Following is the way to recreate the scenario.

          1) check out code from SVN (JBoss_Portal_Branch_2_7).
          2) put the SOP's around this method in CustomizationManagerService.

           if (dashboardPortal == null)
           {
           Portal templatePortal = (Portal)portalObjectContainer.getObject(TEMPLATE_ID);
          
           // Copy the template portal
           System.out.println("templatePortal.copy(dashboardContext, userId, false); =======>start");
           dashboardPortal = (Portal)templatePortal.copy(dashboardContext, userId, false);
           System.out.println("templatePortal.copy(dashboardContext, userId, false); =======>end");
           copy(templatePortal, dashboardContext.getChild(userId));
          
           }
          

          3) compile & deploy and run it. Create some 8-10 users from admin-portlet.
          4) restart the server then login with new users and access the dashboard.

          you will notice so many select queries within those SOP's. N0umber of these select statements are equal to number of dashboard already created in JBP. Following is the output with 3 users.
          
           templatePortal.copy(dashboardContext, userId, false); =======>start
          10:32:03,547 INFO [STDOUT] Hibernate: select displaynam0_.INSTANCE_PK as INSTANCE1_0_, displaynam0_.TEXT as TEXT0_, displaynam0_.LOCALE as LOCALE0_ from JBP_PORTAL_OBJECT_DNAMES displaynam0_ where displaynam0_.INSTANCE_PK=?
          10:32:03,548 INFO [STDOUT] Hibernate: select children0_.PARENT_KEY as PARENT4_1_, children0_.PK as PK1_, children0_.NAME as NAME1_, children0_.PK as PK9_0_, children0_."PATH" as PATH2_9_0_, children0_.NAME as NAME9_0_, children0_.PARENT_KEY as PARENT4_9_0_ from JBP_OBJECT_NODE children0_ where children0_.PARENT_KEY=?
          10:32:03,550 INFO [STDOUT] Hibernate: select portalobje0_.PK as PK10_0_, portalobje0_.LISTENER as LISTENER10_0_, portalobje0_4_.INSTANCE_REF as INSTANCE2_18_0_, case when portalobje0_1_.PK is not null then 1 when portalobje0_2_.PK is not null then 2 when portalobje0_3_.PK is not null then 3 when portalobje0_4_.PK is not null then 4 when portalobje0_.PK is not null then 0 end as clazz_0_, declaredpr1_.OBJECT_KEY as OBJECT1_2_, declaredpr1_.jbp_VALUE as jbp2_2_, declaredpr1_.NAME as NAME2_, modes2_.PK as PK3_, modes2_.name as name3_, windowstat3_.PK as PK4_, windowstat3_.name as name4_ from JBP_PORTAL_OBJECT portalobje0_ left outer join JBP_CONTEXT portalobje0_1_ on portalobje0_.PK=portalobje0_1_.PK left outer join JBP_PORTAL portalobje0_2_ on portalobje0_.PK=portalobje0_2_.PK left outer join JBP_PAGE portalobje0_3_ on portalobje0_.PK=portalobje0_3_.PK left outer join JBP_WINDOW portalobje0_4_ on portalobje0_.PK=portalobje0_4_.PK left outer join JBP_PORTAL_OBJECT_PROPS declaredpr1_ on portalobje0_.PK=declaredpr1_.OBJECT_KEY left outer join JBP_PORTAL_MODE modes2_ on portalobje0_.PK=modes2_.PK left outer join JBP_PORTAL_WINDOW_STATE windowstat3_ on portalobje0_.PK=windowstat3_.PK where portalobje0_.PK=?
          10:32:03,557 INFO [STDOUT] Hibernate: select portalobje0_.PK as PK10_0_, portalobje0_.LISTENER as LISTENER10_0_, portalobje0_4_.INSTANCE_REF as INSTANCE2_18_0_, case when portalobje0_1_.PK is not null then 1 when portalobje0_2_.PK is not null then 2 when portalobje0_3_.PK is not null then 3 when portalobje0_4_.PK is not null then 4 when portalobje0_.PK is not null then 0 end as clazz_0_, declaredpr1_.OBJECT_KEY as OBJECT1_2_, declaredpr1_.jbp_VALUE as jbp2_2_, declaredpr1_.NAME as NAME2_, modes2_.PK as PK3_, modes2_.name as name3_, windowstat3_.PK as PK4_, windowstat3_.name as name4_ from JBP_PORTAL_OBJECT portalobje0_ left outer join JBP_CONTEXT portalobje0_1_ on portalobje0_.PK=portalobje0_1_.PK left outer join JBP_PORTAL portalobje0_2_ on portalobje0_.PK=portalobje0_2_.PK left outer join JBP_PAGE portalobje0_3_ on portalobje0_.PK=portalobje0_3_.PK left outer join JBP_WINDOW portalobje0_4_ on portalobje0_.PK=portalobje0_4_.PK left outer join JBP_PORTAL_OBJECT_PROPS declaredpr1_ on portalobje0_.PK=declaredpr1_.OBJECT_KEY left outer join JBP_PORTAL_MODE modes2_ on portalobje0_.PK=modes2_.PK left outer join JBP_PORTAL_WINDOW_STATE windowstat3_ on portalobje0_.PK=windowstat3_.PK where portalobje0_.PK=?
          10:32:03,564 INFO [STDOUT] Hibernate: select portalobje0_.PK as PK10_0_, portalobje0_.LISTENER as LISTENER10_0_, portalobje0_4_.INSTANCE_REF as INSTANCE2_18_0_, case when portalobje0_1_.PK is not null then 1 when portalobje0_2_.PK is not null then 2 when portalobje0_3_.PK is not null then 3 when portalobje0_4_.PK is not null then 4 when portalobje0_.PK is not null then 0 end as clazz_0_, declaredpr1_.OBJECT_KEY as OBJECT1_2_, declaredpr1_.jbp_VALUE as jbp2_2_, declaredpr1_.NAME as NAME2_, modes2_.PK as PK3_, modes2_.name as name3_, windowstat3_.PK as PK4_, windowstat3_.name as name4_ from JBP_PORTAL_OBJECT portalobje0_ left outer join JBP_CONTEXT portalobje0_1_ on portalobje0_.PK=portalobje0_1_.PK left outer join JBP_PORTAL portalobje0_2_ on portalobje0_.PK=portalobje0_2_.PK left outer join JBP_PAGE portalobje0_3_ on portalobje0_.PK=portalobje0_3_.PK left outer join JBP_WINDOW portalobje0_4_ on portalobje0_.PK=portalobje0_4_.PK left outer join JBP_PORTAL_OBJECT_PROPS declaredpr1_ on portalobje0_.PK=declaredpr1_.OBJECT_KEY left outer join JBP_PORTAL_MODE modes2_ on portalobje0_.PK=modes2_.PK left outer join JBP_PORTAL_WINDOW_STATE windowstat3_ on portalobje0_.PK=windowstat3_.PK where portalobje0_.PK=?
          10:32:03,571 INFO [STDOUT] Hibernate: insert into JBP_OBJECT_NODE (PK, "PATH", NAME, PARENT_KEY) values (null, ?, ?, ?)
          10:32:03,572 INFO [STDOUT] Hibernate: call identity()
          10:32:03,576 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_OBJECT (LISTENER, PK) values (?, ?)
          10:32:03,576 INFO [STDOUT] Hibernate: insert into JBP_PORTAL (PK) values (?)
          10:32:03,577 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_MODE (PK, name) values (?, ?)
          10:32:03,577 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_MODE (PK, name) values (?, ?)
          10:32:03,577 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_MODE (PK, name) values (?, ?)
          10:32:03,577 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_MODE (PK, name) values (?, ?)
          10:32:03,577 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_MODE (PK, name) values (?, ?)
          10:32:03,578 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_WINDOW_STATE (PK, name) values (?, ?)
          10:32:03,578 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_WINDOW_STATE (PK, name) values (?, ?)
          10:32:03,584 INFO [STDOUT] Hibernate: insert into JBP_PORTAL_WINDOW_STATE (PK, name) values (?, ?)
          10:32:03,584 INFO [STDOUT] templatePortal.copy(dashboardContext, userId, false); =======>end
          


          So following query gets fired multiple times.

          select
          portalobje0_.PK as PK10_0_,
          portalobje0_.LISTENER as LISTENER10_0_,
          portalobje0_4_.INSTANCE_REF as INSTANCE2_18_0_,
           case when portalobje0_1_.PK is not null then 1
           when portalobje0_2_.PK is not null then 2
           when portalobje0_3_.PK is not null then 3
           when portalobje0_4_.PK is not null then 4
           when portalobje0_.PK is not null then 0
           end as clazz_0_,
           declaredpr1_.OBJECT_KEY as OBJECT1_2_,
           declaredpr1_.jbp_VALUE as jbp2_2_,
           declaredpr1_.NAME as NAME2_,
           modes2_.PK as PK3_,
           modes2_.name as name3_,
           windowstat3_.PK as PK4_,
           windowstat3_.name as name4_
          from JBP_PORTAL_OBJECT portalobje0_
          left outer join JBP_CONTEXT portalobje0_1_ on portalobje0_.PK=portalobje0_1_.PK
          left outer join JBP_PORTAL portalobje0_2_ on portalobje0_.PK=portalobje0_2_.PK
          left outer join JBP_PAGE portalobje0_3_ on portalobje0_.PK=portalobje0_3_.PK
          left outer join JBP_WINDOW portalobje0_4_ on portalobje0_.PK=portalobje0_4_.PK
          left outer join JBP_PORTAL_OBJECT_PROPS declaredpr1_ on portalobje0_.PK=declaredpr1_.OBJECT_KEY
          left outer join JBP_PORTAL_MODE modes2_ on portalobje0_.PK=modes2_.PK
          left outer join JBP_PORTAL_WINDOW_STATE windowstat3_ on portalobje0_.PK=windowstat3_.PK
          
          where portalobje0_.PK=?


          Any idea/help/thought towards resolving it would be greatly appreciated.


          • 2. Re: JBoss portal performance: (Portal)templatePortal.copy(da

            Request you to please let us know if it is really a bug. If it is, then we would like to open a JIRA and work upon it.

            • 3. Re: JBoss portal performance: (Portal)templatePortal.copy(da

              We have found a work around for this.

              Problem further drilled down to following calls of ObjectNode domain object(void addChild(String name, PortalObjectImpl childObject) of org.jboss.portal.core.impl.model.portal.ObjectNode).

              children.containsKey(name)
              

              Here children is a MAP(One-to-Many association) that is being loaded lazily. Because of this lazy loading, initially it is loaded as a proxy and whenever any operation performed on it, entire map gets loaded that in-turn fires those multiple select queries.

              Proposed Solution

              Solution lies in making this collection lazy="extra" instead of lazy="true" in core/src/resources/portal-core-sar/conf/hibernate/portal/domain.hbm.xml


              From:
              <class
               name="org.jboss.portal.core.impl.model.portal.ObjectNode"
               table="JBP_OBJECT_NODE">
              .....
              <map
               name="children"
               inverse="true"
               cascade="none"
               fetch="select"
               lazy="true">
               <cache usage="@portal.hibernate.cache.usage@"/>
               <key column="PARENT_KEY"/>
               <map-key
               type="org.jboss.portal.jems.hibernate.MagicString"
               column="NAME"/>
               <one-to-many class="org.jboss.portal.core.impl.model.portal.ObjectNode"/>
               </map>


              To:
              <map
               name="children"
               inverse="true"
               cascade="none"
               fetch="select"
               lazy="extra">
               <cache usage="@portal.hibernate.cache.usage@"/>
               <key column="PARENT_KEY"/>
               <map-key
               type="org.jboss.portal.jems.hibernate.MagicString"
               column="NAME"/>
               <one-to-many class="org.jboss.portal.core.impl.model.portal.ObjectNode"/>
               </map>



              The advantage gained by making lazy="extra" to lazy="true", according to hibernate docs,HERE https://hibernate.bluemars.net/315.html.

              "...The collection wrapper is now smarter than before. The collection is no longer initialized if you call size(), contains(), or isEmpty()—the database is queried to retrieve the necessary information. If it’s a Map or a List, the operations containsKey() and get() also query the database directly..."



              After doing this only one query in being fired instead of plethora of queries.