Performance Problem with JpaPermissionStore
mroeoesli Jun 10, 2009 1:52 PMI'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); }