2 Replies Latest reply on Jun 10, 2009 4:06 PM by Marco Röösli

    Performance Problem with JpaPermissionStore

    Marco Röösli Newbie

      I've a performance problem with the JpaPermissionStore.


      There are:
      50 entitites
      5 roles
      6 actions


      I want to grant the 6 actions for all 5 roles on all 50 entities and this takes to much time for me because in my application i will have this case a lot of times.


      I made 4 Tests (database is empty before stating a test):


      Test1:
      Creates a Permission Object for each action and then this list of 6 Permission object will be granted for each role and on each object.
      Takes: 1312 ms for granting


      Test2:
      Creates all Permission Objects first (1500 Permission Objects) and then it grants this list.
      Takes: 1750 ms for granting.


      Test3:
      I don't use the permission store. I use the Entity for the Permissions directly and set the target, action, recipent and the discriminator.
      Takes: 31 ms for granting


      Test3 is much faster. First i guessed it is faster because every action will be granted alone. So I made a test4 where I grant an action set (comma separated action string) directly in one Permission Object but this test was not much faster.
      Takes: 1282 ms for granting


      I also tried to set the FlushMode to Manual on the Session so that queries in the JpaPermissionStore can't force a flush. That had no effect too.


      Dose someone know what element in the JpaPermissionStore makes it so slow? Is it becuase of the queries inside the JpaPermissionStore?
      How can I improve the performance for my case?


      Thank you so much for your help.
      Greetz Marco




      my tests:


      Test1:


      @Test(groups = { "performance" })
         public void jpaPermissionStorePerformanceTest1() throws Exception {
            new ComponentTest() {
      
               @Override
               protected void testComponents() throws Exception {
                  System.out.println("#############################TEST-1####################################");
                  // create and grant the permissions at the same time (each action
                  // for 1 Permission object)
                  JpaPermissionStore jpaPermissionStore = (JpaPermissionStore) Component.getInstance("org.jboss.seam.security.jpaPermissionStore", true);
                  JpaIdentityStore jpaIdentityStore = (JpaIdentityStore) Component.getInstance("org.jboss.seam.security.identityStore", true);
                  Session session = (Session) Component.getInstance(Persistence.DEFAULT_HBM_SESSION_NAME, true);
      
                  UserTransaction transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create dummy Objs
                  List<DummyObject> dummyObjs = createDummyObjs(session, transaction);
      
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create roles
                  List<String> roles = createRoles(session, jpaIdentityStore, transaction);
      
                  System.out.println("#################################################################");
                  System.out.println("# set Permissions for Roles");
                  System.out.println("#################################################################");
                  long ts1 = System.currentTimeMillis();
                  int permissionCount = 0;
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  System.out.println("<-Begin create and grant pemissions");
                  transaction.begin();
                  for (DummyObject dummyObj : dummyObjs) {
                     for (String role : roles) {
                        // create permissions
                        List<Permission> permissions = new ArrayList<Permission>();
                        for (String action : getActions()) {
                           permissions.add(new Permission(dummyObj, action, new org.jboss.seam.security.Role(role)));
                           permissionCount++;
                        }
                        jpaPermissionStore.grantPermissions(permissions);
                     }
                  }
                  transaction.commit();
                  System.out.println("[" + (System.currentTimeMillis() - ts1) + "] ms ->");
      
                  System.out.println(permissionCount + " permissions granted for " + roles.size() + " roles on " + dummyObjs.size() + " dummy objects");
               }
            }.run();
      
         }



      Output:





      #############################TEST-1####################################
      #################################################################
      # create dummy objects
      #################################################################
      
      <-Begin Create dummy objs
      [16] ms ->
      
      #################################################################
      # Create Roles
      #################################################################
      
      <-Begin CreateRoles
      [266] ms ->
      #################################################################
      # set Permissions for Roles
      #################################################################
      <-Begin create and grant pemissions
      [1312] ms ->
      1500 permissions granted for 5 roles on 50 dummy objects"




      Test2


      @Test(groups = { "performance" })
         public void jpaPermissionStorePerformanceTest2() throws Exception {
            new ComponentTest() {
      
               @Override
               protected void testComponents() throws Exception {
                  System.out.println("#############################TEST-2####################################");
                  // first create the permission list and then grant it together (each
                  // action for 1 Permission object)
                  JpaPermissionStore jpaPermissionStore = (JpaPermissionStore) Component.getInstance("org.jboss.seam.security.jpaPermissionStore", true);
                  JpaIdentityStore jpaIdentityStore = (JpaIdentityStore) Component.getInstance("org.jboss.seam.security.identityStore", true);
                  Session session = (Session) Component.getInstance(Persistence.DEFAULT_HBM_SESSION_NAME, true);
      
                  UserTransaction transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create dummy 50 Objs
                  List<DummyObject> dummyObjs = createDummyObjs(session, transaction);
      
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create 5 roles
                  List<String> roles = createRoles(session, jpaIdentityStore, transaction);
      
                  System.out.println("#################################################################");
                  System.out.println("# set Permissions for Roles");
                  System.out.println("#################################################################");
                  long ts1 = System.currentTimeMillis();
                  List<Permission> permissions = new ArrayList<Permission>();
                  System.out.println("<-Begin create pemissions");
      
                  for (DummyObject dummyObj : dummyObjs) {
                     for (String role : roles) {
                        // create permissions
                        for (String action : getActions()) {
                           permissions.add(new Permission(dummyObj, action, new org.jboss.seam.security.Role(role)));
                        }
                     }
                  }
                  System.out.println("[" + (System.currentTimeMillis() - ts1) + "] ms ->");
      
                  // grant permissions
                  long ts2 = System.currentTimeMillis();
                  System.out.println("<-Begin grant permissions ");
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  transaction.begin();
                  session.setFlushMode(FlushMode.MANUAL);
                  jpaPermissionStore.grantPermissions(permissions);
                  session.setFlushMode(FlushMode.AUTO);
                  session.flush();
                  transaction.commit();
                  System.out.println("[" + (System.currentTimeMillis() - ts2) + "] ms ->");
                  System.out.println("time for grant and create permissions together[" + (System.currentTimeMillis() - ts1) + "] ms");
                  System.out.println(permissions.size() + " permissions granted for " + roles.size() + " roles on " + dummyObjs.size() + " dummy objects");
      
               }
            }.run();
      
         }



      output


      #############################TEST-2####################################
      #################################################################
      # create dummy objects
      #################################################################
      
      <-Begin Create dummy objs
      [93] ms ->
      
      #################################################################
      # Create Roles
      #################################################################
      
      <-Begin CreateRoles
      [31] ms ->
      #################################################################
      # set Permissions for Roles
      #################################################################
      <-Begin create pemissions
      [0] ms ->
      <-Begin grant permissions 
      [1750] ms ->
      time for grant and create permissions together[1750] ms
      1500 permissions granted for 5 roles on 50 dummy objects




      Test3




      @Test(groups = { "performance" })
         public void jpaPermissionStorePerformanceTest3() throws Exception {
            new ComponentTest() {
      
               @Override
               protected void testComponents() throws Exception {
                  System.out.println("#############################TEST-3####################################");
                  // grant permissions direct with the entity (without using the
                  // jpaPermissionStore)
                  JpaIdentityStore jpaIdentityStore = (JpaIdentityStore) Component.getInstance("org.jboss.seam.security.identityStore", true);
                  Session session = (Session) Component.getInstance(Persistence.DEFAULT_HBM_SESSION_NAME, true);
      
                  UserTransaction transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create dummy 50 Objs
                  List<DummyObject> dummyObjs = createDummyObjs(session, transaction);
      
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create 5 roles
                  List<String> roles = createRoles(session, jpaIdentityStore, transaction);
      
                  System.out.println("#################################################################");
                  System.out.println("# set Permissions for Roles (without the permission Store)");
                  System.out.println("#################################################################");
                  long ts1 = System.currentTimeMillis();
      
                  System.out.println("<-Begin store Permissions");
                  transaction.begin();
                  int permissionsCount = 0;
                  for (DummyObject dummyObj : dummyObjs) {
                     for (String role : roles) {
                        AccountPermission accountPermission = new AccountPermission();
                        accountPermission.setTarget(dummyObj.getId());
                        accountPermission.setAction(getActionString(getActions()));
                        accountPermission.setRecipient(role);
                        accountPermission.setDiscriminator("role");
                        session.save(accountPermission);
                        permissionsCount++;
                     }
                  }
                  System.out.println("[" + (System.currentTimeMillis() - ts1) + "] ms ->");
      
                  transaction.commit();
                  System.out.println(permissionsCount + " permissions granted for " + roles.size() + " roles on " + dummyObjs.size() + " dummy objects");
      
               }
            }.run();
      
         }



      Output:



      #############################TEST-3####################################
      #################################################################
      # create dummy objects
      #################################################################
      
      <-Begin Create dummy objs
      [31] ms ->
      
      #################################################################
      # Create Roles
      #################################################################
      
      <-Begin CreateRoles
      [31] ms ->
      #################################################################
      # set Permissions for Roles (without the permission Store)
      #################################################################
      <-Begin store Permissions
      [31] ms ->
      250 permissions granted for 5 roles on 50 dummy objects




      Test4



       @Test(groups = { "performance" })
         public void jpaPermissionStorePerformanceTest4() throws Exception {
            new ComponentTest() {
      
               @Override
               protected void testComponents() throws Exception {
                  System.out.println("#############################TEST-4####################################");
                  // first create the permission list and then grant it together (all
                  // actions in 1 Permission object)
                  JpaPermissionStore jpaPermissionStore = (JpaPermissionStore) Component.getInstance("org.jboss.seam.security.jpaPermissionStore", true);
                  JpaIdentityStore jpaIdentityStore = (JpaIdentityStore) Component.getInstance("org.jboss.seam.security.identityStore", true);
                  Session session = (Session) Component.getInstance(Persistence.DEFAULT_HBM_SESSION_NAME, true);
      
                  UserTransaction transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create dummy 50 Objs
                  List<DummyObject> dummyObjs = createDummyObjs(session, transaction);
      
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  // create 5 roles
                  List<String> roles = createRoles(session, jpaIdentityStore, transaction);
      
                  System.out.println("#################################################################");
                  System.out.println("# set Permissions for Roles");
                  System.out.println("#################################################################");
                  long ts1 = System.currentTimeMillis();
                  List<Permission> permissions = new ArrayList<Permission>();
                  System.out.println("<-Begin create pemissions");
      
                  for (DummyObject dummyObj : dummyObjs) {
                     for (String role : roles) {
                        // create permissions
                        permissions.add(new Permission(dummyObj, getActionString(getActions()), new org.jboss.seam.security.Role(role)));
                     }
                  }
                  System.out.println("[" + (System.currentTimeMillis() - ts1) + "] ms ->");
      
                  // grant permissions
                  long ts2 = System.currentTimeMillis();
                  System.out.println("<-Begin grant permissions ");
                  transaction = Transaction.instance();
                  Assert.assertFalse(transaction.isActive());
                  transaction.begin();
                  jpaPermissionStore.grantPermissions(permissions);
                  transaction.commit();
                  System.out.println("[" + (System.currentTimeMillis() - ts2) + "] ms ->");
                  System.out.println("time for grant and create permissions together[" + (System.currentTimeMillis() - ts1) + "] ms");
                  System.out.println(permissions.size() + " permissions granted for " + roles.size() + " roles on " + dummyObjs.size() + " dummy objects");
      
               }
            }.run();
      
         }



      Output:


      #############################TEST-3####################################
      #################################################################
      # create dummy objects
      #################################################################
      
      <-Begin Create dummy objs
      [15] ms ->
      
      #################################################################
      # Create Roles
      #################################################################
      
      <-Begin CreateRoles
      [16] ms ->
      #################################################################
      # set Permissions for Roles
      #################################################################
      <-Begin create pemissions
      [0] ms ->
      <-Begin grant permissions 
      [1282] ms ->
      time for grant and create permissions together[1282] ms
      250 permissions granted for 5 roles on 50 dummy objects



      Some helper methods:



      private List<String> createRoles(Session session, JpaIdentityStore jpaIdentityStore, UserTransaction transaction) throws Exception {
      
            System.out.println("");
            System.out.println("#################################################################");
            System.out.println("# Create Roles");
            System.out.println("#################################################################");
            System.out.println("");
      
            List<String> roles = new ArrayList<String>();
            long ts1 = System.currentTimeMillis();
            System.out.println("<-Begin CreateRoles");
            transaction.begin();
            for (int i = 0; i < 5; i++) {
               roles.add("role" + i);
               jpaIdentityStore.createRole("role" + i);
            }
            transaction.commit();
            System.out.println("[" + (System.currentTimeMillis() - ts1) + "] ms ->");
      
            return roles;
         }
      
         private List<DummyObject> createDummyObjs(Session session, UserTransaction transaction) throws Exception {
            transaction.begin();
            System.out.println("#################################################################");
            System.out.println("# create dummy objects");
            System.out.println("#################################################################");
            System.out.println("");
            long ts0 = System.currentTimeMillis();
            System.out.println("<-Begin Create dummy objs");
            List<DummyObject> dummyObjs = new ArrayList<DummyObject>();
            for (int i = 0; i < 50; i++) {
               DummyObject dummyObj = new DummyObject();
               dummyObj.setName("name" + i);
               session.save(dummyObj);
               dummyObjs.add(dummyObj);
            }
            transaction.commit();
            System.out.println("[" + (System.currentTimeMillis() - ts0) + "] ms ->");
            return dummyObjs;
         }
      
         private List<String> getActions() {
            List<String> actions = new ArrayList<String>();
            for (int i = 0; i < 6; i++) {
               actions.add("action" + 1);
            }
            return actions;
         }
      
         private String getActionString(List<String> actions) {
            String result = "";
            for (String action : actions) {
               result += action + ",";
            }
            return result.substring(0, result.length() - 1);
         }





        • 1. Re: Performance Problem with JpaPermissionStore
          Leo van den berg Master

          Check you generated sql to see what is done under the hood and use that as a starting point for improvement.


          • 2. Re: Performance Problem with JpaPermissionStore
            Marco Röösli Newbie

            Thx for your hint leo


            I found out that my JpaPermissionStore is using an other session as the Session which i manipulated with FlushMode.
            Now I set the FlushMode to MANUAL on the Session what is used by the JpaPermissionStore.


            this FlushMode manipulation makes it much faster
            Test1,2,3 take now more or less 500ms.


            I also setted up this 2 properties in my Hibernate Config:


                  <property name="hibernate.order_inserts" value="true" />
                   <property name="hibernate.order_updates" value="true" />



            now it takes more or less 280ms


            but I think there is still potential to improve the speed. 280ms is factor 9 to 31ms.


            I think the queries in the JpaPermissionStore takes the most of the time. Im my case I know that the objects (targets) are new and the roles too.
            I guess in this special case it's not necessary to query something. Or is there a error in reasoning? Is it a good idea to override the JpaPermissionStore and do a mechanism to grant permissions for new objects and new roles?


            Thx for your help!


            this are sql operations what will be done by test2:


            #############################TEST-2####################################
            #################################################################
            # create dummy objects
            #################################################################
            
            <-Begin Create dummy objs
            [32] ms ->
            
            #################################################################
            # Create Roles
            #################################################################
            
            <-Begin CreateRoles
            Hibernate: select role0_.ID as ID426_, role0_.OBJ_VERSION as OBJ2_426_, role0_.NAME as NAME426_ from ROLES role0_ where role0_.NAME=? limit ?
            Hibernate: insert into ROLES (OBJ_VERSION, NAME, ID) values (?, ?, ?)
            Hibernate: select role0_.ID as ID426_, role0_.OBJ_VERSION as OBJ2_426_, role0_.NAME as NAME426_ from ROLES role0_ where role0_.NAME=? limit ?
            Hibernate: insert into ROLES (OBJ_VERSION, NAME, ID) values (?, ?, ?)
            Hibernate: select role0_.ID as ID426_, role0_.OBJ_VERSION as OBJ2_426_, role0_.NAME as NAME426_ from ROLES role0_ where role0_.NAME=? limit ?
            Hibernate: insert into ROLES (OBJ_VERSION, NAME, ID) values (?, ?, ?)
            Hibernate: select role0_.ID as ID426_, role0_.OBJ_VERSION as OBJ2_426_, role0_.NAME as NAME426_ from ROLES role0_ where role0_.NAME=? limit ?
            Hibernate: insert into ROLES (OBJ_VERSION, NAME, ID) values (?, ?, ?)
            Hibernate: select role0_.ID as ID426_, role0_.OBJ_VERSION as OBJ2_426_, role0_.NAME as NAME426_ from ROLES role0_ where role0_.NAME=? limit ?
            Hibernate: insert into ROLES (OBJ_VERSION, NAME, ID) values (?, ?, ?)
            [203] ms ->
            #################################################################
            # set Permissions for Roles
            #################################################################
            <-Begin create pemissions
            [0] ms ->
            <-Begin grant permissions 
            Hibernate: /* select p from org.dummy.app.security.model.AccountPermission p where p.target = :target and p.recipient = :recipient and p.discriminator = :discriminator */ select accountper0_.id as id308_, accountper0_.ACTION as ACTION308_, accountper0_.discriminator as discrimi3_308_, accountper0_.RECIPIENT as RECIPIENT308_, accountper0_.TARGET as TARGET308_ from ACCOUNTPERMISSION accountper0_ where accountper0_.TARGET=? and accountper0_.RECIPIENT=? and accountper0_.discriminator=?
            Hibernate: /* select p from org.dummy.app.security.model.AccountPermission p where p.target = :target and p.recipient = :recipient and p.discriminator = :discriminator */ select accountper0_.id as id308_, accountper0_.ACTION as ACTION308_, accountper0_.discriminator as discrimi3_308_, accountper0_.RECIPIENT as RECIPIENT308_, accountper0_.TARGET as TARGET308_ from ACCOUNTPERMISSION accountper0_ where accountper0_.TARGET=? and accountper0_.RECIPIENT=? and accountper0_.discriminator=?
            .....
            //250 secllects
            
            Hibernate: /* insert org.dummy.app.security.model.DummyObject */ insert into DummyObject (OBJ_VERSION, name, ID) values (?, ?, ?)
            Hibernate: /* insert org.dummy.app.security.model.DummyObject */ insert into DummyObject (OBJ_VERSION, name, ID) values (?, ?, ?)
            ....
            //250 inserts
            
            [280] ms ->
            time for grant and create permissions together[422] ms
            1500 permissions granted for 5 roles on 50 dummy objects