These are my findings during my investigation of the
"IntitialContext.lookup" calls. Remember from my previous email that all
lookups are routed through the "org.jboss.seam.util.Naming" class.
Where do we do JNDI lookups?
---------------------------------------
Below are all of the places in the code where Seam performs these look ups:
* org.jboss.seam.bpm.Jbpm.initJbpmConfiguration()*
- Naming.getInitialContext().lookup(jbpmConfigurationJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/bpm/Jb...
* org.jboss.seam.jms.ManagedQueueSender.getQueue()*
- Naming.getInitialContext().lookup(queueJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/jms/Ma...
* org.jboss.seam.jms.ManagedTopicPublisher.getTopic()*
- Naming.getInitialContext().lookup(topicJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/jms/Ma...
* org.jboss.seam.jms.QueueConnection.getQueueConnectionFactory()*
- Naming.getInitialContext().lookup(queueConnectionFactoryJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/jms/Qu...
* org.jboss.seam.jms.TopicConnection.getTopicConnectionFactory()*
- Naming.getInitialContext().lookup(topicConnectionFactoryJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/jms/To...
* org.jboss.seam.mail.MailSession.getSession()*
- Naming.getInitialContext().lookup(getSessionJndiName());
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/mail/M...
*
org.jboss.seam.persistence.ManagedHibernateSession.getSessionFactoryFromJndiOrValueBinding()*
- Naming.getInitialContext().lookup(sessionFactoryJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/persis...
*
org.jboss.seam.persistence.ManagedPersistenceContext.getEntityManagerFactoryFromJndiOrValueBinding()*
- Naming.getInitialContext().lookup(persistenceUnitJndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/persis...
* org.jboss.seam.transaction.Transaction.getUserTransaction()*
- Naming.getInitialContext();
- context.lookup("java:comp/UserTransaction");
- context.lookup("UserTransaction");
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/transa...
* org.jboss.seam.util.EJB.getEJBContext()*
- Naming.getInitialContext().lookup(ejbContextName);
- Naming.getInitialContext().lookup(STANDARD_EJB_CONTEXT_NAME);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/util/E...
* org.jboss.seam.Component.instantiateSessionBean()*
- Naming.getInitialContext().lookup(jndiName);
-
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/Compon...
JNDI Lookups
---------------------
The important thing to investigate is who the the big culprit(s) are - who
is making all the lookups. We all obviously had our suspicions, and they
were right.
A single user making a single request to the Seam user forum front page
performs 114 JNDI lookups for "java:comp/UserTransation". This means that
not only are 144 instances of IntialContext created, but we have 114 actual
lookups as well. This is nearly linear with 2 requests creating 228 JNDI
lookups + some for ajax4jsf caching calls as described below. Extrapolating
to the 25 user test that would be 25x114=2850 jndi lookups for each round of
requests.
At least for the wiki page I am testing there were no other JNDI lookups.
Who is looking up "java:comp/UserTransation"
--------------------------------------------------------
All of these calls can be traced to Transaction.instance(). I broke down
all of the calls to Transaction.instance() during a single request to the
user forum page on the wiki.
81 - seam.util.Work.workInTransaction(Work.java:34) via
(TransactionInterceptor.java:34)
1 -
SeamPhaseListener.handleTransactionsBeforePhase(SeamPhaseListener.java:319)
3 -
SeamPhaseListener.begin(SeamPhaseListener.java:591)
3 -
SeamPhaseListener.begin(SeamPhaseListener.java:594)
3 - SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:611)
3 - SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:614)
8 -
ManagedPersistenceContext.joinTransaction(ManagedPersistenceContext.java:120)
6 -
Contexts.flushAndDestroyContexts(Contexts.java:331)
6 -
ManagedPersistenceContext.close(ManagedPersistenceContext.java:192)
-------------
114 - Total
I then broke it down by which JSF lifecycle phase it was done in.
Phase Breakdown:
------------------
3 - During RESTORE_VIEW
2 - Between RESTORE_VIEW and RENDER_RESPONSE
91 - During RENDER_RESPONSE
18 - After RENDER_RESPONSE
----------
114 total
I then did the same break down on a second follow up request with the same
session
Second Request showed a different distribution:
------------------------------------------------
3 - During RESTORE_VIEW
2 - Between RESTORE_VIEW and RENDER_RESPONSE
91 - During RENDER_RESPONSE
5 - After RENDER_RESPONSE
3 - During 2nd RESTORE_VIEW
0 - Between 2nd RESTORE_VIEW and RENDER_RESPONSE
1 - During 2nd RENDER_RESPONSE
3 - After 2nd RENDER_RESPONSE
3 - During 3rd RESTORE_VIEW
0 - Between 3rd RESTORE_VIEW and RENDER_RESPONSE
1 - During 3rd RENDER_RESPONSE
16 - After 3rd RENDER_RESPONSE
------------
128 total
The extra 14 lookups are all during the extra 2 mini requests. They all
pass through this ajax4jsf class
"org.ajax4jsf.resource.ResourceLifecycle.invokePhaseListener(ResourceLifecycle.java:[199/201])".
I'm assuming that these extra calls are related to page fragment caching
and/or resources that are provided through the ajax4jsf
InternetResourceService. Christian can you confirm?
Conclusions:
---------------------
We obviously need to find more ways to improve this behavior. The primary
offender is "Work.java" (see:
http://fisheye.jboss.org/browse/Seam/trunk/src/main/org/jboss/seam/util/W...).
This single line is checking if the transaction is currently active.
81
time it is active and processing continues as normal. Is there a way we can
cache this value for the length of the request (either the transaction, or
the result)? Caching the result could be bad if something changed during
the request, so we would need the actual transaction.
Also many of the lookups were the result of EL processing during the
RENDER_RESPONSE phase. Ideally these would primarily be read-only requests
or close to it. Could there be a way to disable the transactional calls for
items somehow tagged read only? I have not give that much thought yet so it
might need some flushing out ;-)
These finding just cover the wiki application. We need to do similar
investigations with other applications like dvdstore and chatroom to
exercise some of the other areas.
More to come, but any comments suggestions, or ideas for improving this are
welcome :-)
-Jay
--
blog:
http://in.relation.to/Bloggers/Jay