-
1. Re: Seam Manager Persistence
christian.bauer Apr 4, 2008 4:30 PM (in response to graben)I think it might be that you have the wrong polarity in your neutron flow.
-
2. Re: Seam Manager Persistence
yk Apr 4, 2008 4:54 PM (in response to graben)See Caching Chapter of the Seam Documentation:
In particular, the Seam-managed persistence context (or an extended EJB container-managed persistence context associated with a conversation-scoped stateful session bean) acts as a cache of data that has been read in the current conversation. This cache tends to have a pretty high hitrate! Seam optimizes the replication of Seam-managed persistence contexts in a clustered environment, and there is no requirement for transactional consistency with the database (optimistic locking is sufficient) so you don't need to worry too much about the performance implications of this cache, unless you read thousands of objects into a single persistence context.
.... -
3. Re: Seam Manager Persistence
christian.bauer Apr 4, 2008 5:10 PM (in response to graben)This paragraph has nothing to do with the problem of the original posters. In fact, unless magic crystal balls start working, nobody knows what their problem is.
-
4. Re: Seam Manager Persistence
jimk1723 Apr 4, 2008 6:51 PM (in response to graben)I think I need to third this; I noticed it after profiling my app in YourKit. My
note to self
dates back to November though, so I'll need to refresh my memory on what was going on... -
5. Re: Seam Manager Persistence
gjeudy Apr 4, 2008 7:55 PM (in response to graben)Are you using the Seam entityConverter ? If so, that thread might be related to the performance hit you are witnessing.
I think a proposed fix is posted at the end of this thread. Anyways you should use query-driven paging mechanism if you are dealing with thousands of entities...
-
6. Re: Seam Manager Persistence
jimk1723 Apr 4, 2008 10:04 PM (in response to graben)Huh, yeah actually. In a bunch of places...with entity backed selectOneMenus. I'll take a look at that thread.
-
7. Re: Seam Manager Persistence
graben Apr 8, 2008 8:18 PM (in response to graben)Thank you for any helpful comment so far! After a very long and sometimes frustrating time of profiling and debugging I think I got closer to the underlying problem. I recognized that Seam tries to passivate every entity after jsf request has been finished that has been loaded during that request and conversation.
ServerConversationContext.flush() --> ServerConversationContext.isAttributeDirty() --> EntityBeanList.passivate() --> EntityBeanList.passivateAll() --> PassivatedEntity.passivateEntity()
This seems to try to get every single instance from the database. Maybe the reason for so many transactions. I don't know whether that is necessary and why there is so many time lost. I will do further investigation but those sourcecode files a hardly commented. I would suggest to close this gap between claim and reality!I hope that we got this solved!
Greets Benjamin
-
8. Re: Seam Manager Persistence
graben Apr 9, 2008 5:21 PM (in response to graben)Another performance killer found!
class EntityBeanList protected void passivateAll() { List<PassivatedEntity> newPassivatedList = new ArrayList<PassivatedEntity>(list.size()); boolean found = false; for (int i=0; i<list.size(); i++) { PassivatedEntity passivatedEntity = null; Object value = list.get(i); if (value != null) { passivatedEntity = PassivatedEntity.passivateEntity(value); if (passivatedEntity!=null) { if (!found) { list = new ArrayList(list); found=true; } //this would be dangerous, except that we //are doing it to a copy of the original //list: list.set(i, null); } } newPassivatedList.add(passivatedEntity); } // if the original list was nulled out, we don't want to overwrite the passivatedEntity list if (found) { passivatedEntityList = newPassivatedList; } }
Well, bad performance with LinkedList cause of list.get(). Why not using iterator?
-
9. Re: Seam Manager Persistence
pmuir Apr 10, 2008 11:59 AM (in response to graben)
Benjamin Graf wrote on Apr 08, 2008 08:18 PM:
This seems to try to get every single instance from the database. Maybe the reason for so many transactions.Shouldn't do any loads, but just retrieve entities that are already loaded and have been outjected.
I don't know whether that is necessary and why there is so many time lost. I will do further investigation but those sourcecode files a hardly commented.The purpose of the code is pretty much self-evident.
Well, bad performance with LinkedList cause of list.get(). Why not using iterator?If the performance of doing a search of linked list is better using an iterator why does the implementation of get() in the SDK not use it?
-
10. Re: Seam Manager Persistence
graben Apr 10, 2008 2:03 PM (in response to graben)
If the performance of doing a search of linked list is better using an iterator why does the implementation of get() in the SDK not use it?
Well, the SDK is doing the right job with get() if you want to get a specific index item. But in Seam this method is used in a for loop that will touch every single item of the list. For this purpose the iterator should be used instead of the loop because this cause a nested loop in java stack! (for loop in EntityBeanList and for loop in LinkedList -> 1000 items => 10002 = 1000000 actions)
Greets Benjamin
-
11. Re: Seam Manager Persistence
graben Apr 11, 2008 8:20 AM (in response to graben)
Shouldn't do any loads, but just retrieve entities that are already loaded and have been outjected.But what about entities that just have been created and not yet been persisted? As far as I understand the seam code it will try to find even those entity instances in entitymanager 2nd level pool without success --> transactions to the database to find them?
-
12. Re: Seam Manager Persistence
pmuir Apr 14, 2008 12:21 AM (in response to graben)
Benjamin Graf wrote on Apr 10, 2008 02:03 PM:
If the performance of doing a search of linked list is better using an iterator why does the implementation of get() in the SDK not use it?
Well, the SDK is doing the right job with get() if you want to get a specific index item. But in Seam this method is used in a for loop that will touch every single item of the list. For this purpose the iterator should be used instead of the loop because this cause a nested loop in java stack! (for loop in EntityBeanList and for loop in LinkedList -> 1000 items => 10002 = 1000000 actions)I see your point, please raise an issue in JIRA.
-
13. Re: Seam Manager Persistence
pmuir Apr 14, 2008 12:28 AM (in response to graben)I don't think so, from PassivatedEntity.createUsingEntityManager() the passivated entity metadata is only build if the entity is managed (i.e. the current SMPC contains the entity).
-
14. Re: Seam Manager Persistence
graben May 13, 2008 6:55 PM (in response to graben)Quiet a long time ago, I know! Well, I recognized that the problem is a bit earlier while retrieving persistence context. For every entity instance seam tries to get a persistenceContext (PassivatedEntity.passivateEntity).
public static PassivatedEntity passivateEntity(Object value) { Class entityClass = Seam.getEntityClass( value.getClass() ); if (entityClass!=null) { for ( String persistenceContextName: PersistenceContexts.instance().getTouchedContexts() ) { Object persistenceContext = Component.getInstance(persistenceContextName); return createPassivatedEntity(value, entityClass, persistenceContextName, persistenceContext); } } return null; }
If you go further in the java stack you'll get to ManagedPersistenceContext.getEntityManager(). In my case this method wants to join a transaction.
@Unwrap public EntityManager getEntityManager() throws NamingException, SystemException { if (entityManager==null) initEntityManager(); if ( !synchronizationRegistered && !Lifecycle.isDestroying() ) { joinTransaction(); } return entityManager; } private void joinTransaction() throws SystemException { UserTransaction transaction = Transaction.instance(); if ( transaction.isActive() ) { transaction.enlist(entityManager); try { transaction.registerSynchronization(this); synchronizationRegistered = true; } catch (Exception e) { synchronizationRegistered = PersistenceProvider.instance().registerSynchronization(this, entityManager); } } }
That causes a initialization of a new UserTransaction which leeds to a lookup of context.lookup("java:comp/UserTransaction").
protected javax.transaction.UserTransaction getUserTransaction() throws NamingException { InitialContext context = Naming.getInitialContext(); try { return (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction"); } catch (NameNotFoundException nnfe) { try { //Embedded JBoss has no java:comp/UserTransaction javax.transaction.UserTransaction ut = (javax.transaction.UserTransaction) context.lookup("UserTransaction"); ut.getStatus(); //for glassfish, which can return an unusable UT return ut; } catch (Exception e) { throw nnfe; } } }
I don't think that this behaviour is really helpful!