Performance like a line of schoolkids awaiting first Jab.
tony.herstell1 Aug 12, 2008 1:38 AMI have a page that is running appallingly slow.
I have provided code below.
Question 1: Can anyone spot the problem?
Question 2: What tools are recommended for analysing the problem.
This is running on Prod just as slow (if not slower) than Dev.
There are a lot of set/gets as @Out with boolean doesn't work so you have to add routines (not that I even found why in the manual). Another little quirk of Seam I guess. Have code with @Out for most private values and then put/get for booleans...
Given this:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" template="/WEB-INF/pages/templateCleanWithConversations.xhtml"> <!-- content --> <ui:define name="template_title"> <h:outputText value="#{messages.user_list_page}" /> </ui:define> <ui:define name="template_content"> <div id="reg_form"> <h:form class="general_form"> <fieldset class="general_form_fieldset"> <legend class="general_form_legend"> <h:outputText value="#{messages.user_list_fieldset}" /> </legend> <s:validateAll> <!-- CONTROLS --> <div class="left"> <span class="padded_right_left"> <h:outputLabel for="show_avatar" value="Show Avatar"/> <h:selectBooleanCheckbox id="show_avatar" value="#{userListController.showingAvatar}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_email" value="Show Email"/> <h:selectBooleanCheckbox id="show_email" value="#{userListController.showingEmail}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_phone" value="Show Phone"/> <h:selectBooleanCheckbox id="show_phone" value="#{userListController.showingPhone}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_dressage" value="Show Dressage"/> <h:selectBooleanCheckbox id="show_dressage" value="#{userListController.showingDressage}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_sj" value="Show SJ"/> <h:selectBooleanCheckbox id="show_sj" value="#{userListController.showingSJ}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_showing" value="Show Showing"/> <h:selectBooleanCheckbox id="show_showing" value="#{userListController.showingShowing}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_events" value="Show Events"/> <h:selectBooleanCheckbox id="show_events" value="#{userListController.showingEvents}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> <span class="padded_right_left"> <h:outputLabel for="show_dates" value="Show Dates"/> <h:selectBooleanCheckbox id="show_dates" value="#{userListController.showingDates}"> <a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" /> </h:selectBooleanCheckbox> </span> </div> <div> <br/> <br/> </div> <!-- TABLE --> <rich:dataTable id="users_list" value="#{userList}" var="eachUser" columnClasses="center" rows="20" width="100%"> <f:facet name="header"> <h:outputText value="Users" /> </f:facet> <rich:column rendered="#{userListController.isShowingAvatar() eq true}"> <f:facet name="header"> <h:outputText value="Avatar" /> </f:facet> <s:graphicImage width="75px" rendered="#{eachUser.avatar ne null}" value="#{eachUser.avatar.image}" /> </rich:column> <rich:column sortBy="#{eachUser.surname}"> <f:facet name="header"> <h:outputText value="Surname" /> </f:facet> <h:outputText value="#{eachUser.surname}" /> </rich:column> <rich:column sortBy="#{eachUser.firstname}"> <f:facet name="header"> <h:outputText value="Firstname" /> </f:facet> <h:outputText value="#{eachUser.firstname}" /> </rich:column> <rich:column rendered="#{userListController.isShowingEmail() eq true}"> <f:facet name="header"> <h:outputText value="Email" /> </f:facet> <h:outputText value="#{eachUser.email}" /> </rich:column> <rich:column sortBy="#{eachUser.homePhone}" rendered="#{userListController.isShowingPhone() eq true}"> <f:facet name="header"> <h:outputText value="Home Phone" /> </f:facet> <h:outputText value="#{eachUser.homePhone}" /> </rich:column> <rich:column sortBy="#{eachUser.mobilePhone}" rendered="#{userListController.isShowingPhone() eq true}"> <f:facet name="header"> <h:outputText value="Mobile Phone" /> </f:facet> <h:outputText value="#{eachUser.mobilePhone}" /> </rich:column> <rich:column sortBy="#{eachUser.phoneContactOk}" rendered="#{userListController.isShowingPhone() eq true}"> <f:facet name="header"> <h:outputText value="Phone Contact Ok" /> </f:facet> <s:graphicImage rendered="#{eachUser.phoneContactOk}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.phoneContactOk}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.dressageJudge}" rendered="#{userListController.isShowingDressage() eq true}"> <f:facet name="header"> <h:outputText value="Dressage Judge" /> </f:facet> <s:graphicImage rendered="#{eachUser.dressageJudge}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.dressageJudge}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.dressageWriter}" rendered="#{userListController.isShowingDressage() eq true}"> <f:facet name="header"> <h:outputText value="Dressage Writer" /> </f:facet> <s:graphicImage rendered="#{eachUser.dressageWriter}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.dressageWriter}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.dressageHelper}" rendered="#{userListController.isShowingDressage() eq true}"> <f:facet name="header"> <h:outputText value="Dressage Helper" /> </f:facet> <s:graphicImage rendered="#{eachUser.dressageHelper}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.dressageHelper}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.sjJudge}" rendered="#{userListController.isShowingSJ() eq true}"> <f:facet name="header"> <h:outputText value="SJ Judge" /> </f:facet> <s:graphicImage rendered="#{eachUser.sjJudge}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.sjJudge}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.sjHelper}" rendered="#{userListController.isShowingSJ() eq true}"> <f:facet name="header"> <h:outputText value="SJ Helper" /> </f:facet> <s:graphicImage rendered="#{eachUser.sjHelper}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.sjHelper}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.showingJudge}" rendered="#{userListController.isShowingShowing() eq true}"> <f:facet name="header"> <h:outputText value="Showing Judge" /> </f:facet> <s:graphicImage rendered="#{eachUser.showingJudge}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.showingJudge}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.showingHelper}" rendered="#{userListController.isShowingShowing() eq true}"> <f:facet name="header"> <h:outputText value="Showing Helper" /> </f:facet> <s:graphicImage rendered="#{eachUser.showingHelper}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.showingHelper}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.eventsHelper}" rendered="#{userListController.isShowingEvents() eq true}"> <f:facet name="header"> <h:outputText value="Events Helper" /> </f:facet> <s:graphicImage rendered="#{eachUser.eventsHelper}" url="/images/tick.gif" /> <s:graphicImage rendered="#{not eachUser.eventsHelper}" url="/images/cross.gif" /> </rich:column> <rich:column sortBy="#{eachUser.dates.creationDate}" rendered="#{userListController.isShowingDates() eq true}"> <f:facet name="header"> <h:outputText value="Creation Date" /> </f:facet> <h:outputText value="#{eachUser.dates.creationDate}"> <s:convertDateTime pattern="dd/MMM/yyyy"/> </h:outputText> </rich:column> </rich:dataTable> <rich:datascroller for="users_list" maxPages="30"/> </s:validateAll> <div class="general_form_buttons"> <h:commandButton class="general_form_button" action="#{userListController.cancel}" value="#{messages.general_button_cancel}" immediate="true" type="submit"> <s:conversationPropagation type="end" /> </h:commandButton> </div> </fieldset> </h:form> </div> <a4j:status> <f:facet name="start"> <h:graphicImage styleClass="page_foot_image" value="/images/ajax/animated_horse.gif" height="50" /> </f:facet> </a4j:status> </ui:define> <!-- content --> </ui:composition>
Running over this code:
package nz.co.selwynequestriancentre.action.user; import java.io.Serializable; import javax.ejb.Remove; import javax.ejb.Stateful; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; import nz.co.selwynequestriancentre.model.entity.User; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.Conversational; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.End; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.datamodel.DataModel; import org.jboss.seam.log.Log; import java.util.List; /** * @author Tony Herstell * @version $Revision: 1.2 $ $Date: 2008-08-11 07:09:14 $ */ @SuppressWarnings("serial") @Stateful @Name("userListController") @Conversational @Scope(value=ScopeType.CONVERSATION) public class UserListControllerImpl implements UserListController, Serializable { /** * Inject and leverage the Seam Logger. */ @Logger private Log log; /** * Inject the EJB3 Persistence context in EXTENDED mode so will remain * "current" over multiple client/server round trips. */ @PersistenceContext(type=PersistenceContextType.EXTENDED) private EntityManager em; @DataModel private List<User> userList; private boolean showingAvatar = false; private boolean showingEmail = false; private boolean showingPhone = true; private boolean showingDressage = true; private boolean showingSJ = false; private boolean showingShowing = false; private boolean showingEvents = false; private boolean showingDates = false; @Factory("userList") @TransactionAttribute(TransactionAttributeType.REQUIRED) public void findUsers() { userList = em.createQuery("from User user order by user.surname asc").getResultList(); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Begin public String enter() { return "userListController"; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingAvatar() { return showingAvatar; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingAvatar(boolean showingAvatar) { this.showingAvatar = showingAvatar; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingEmail() { return showingEmail; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingEmail(boolean showingEmail) { this.showingEmail = showingEmail; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingPhone() { return showingPhone; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingPhone(boolean showingPhone) { this.showingPhone = showingPhone; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingDressage() { return showingDressage; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingDressage(boolean showingDressage) { this.showingDressage = showingDressage; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingSJ() { return showingSJ; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingSJ(boolean showingSJ) { this.showingSJ = showingSJ; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingShowing() { return showingShowing; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingShowing(boolean showingShowing) { this.showingShowing = showingShowing; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingEvents() { return showingEvents; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingEvents(boolean showingEvents) { this.showingEvents = showingEvents; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public boolean isShowingDates() { return showingDates; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void setShowingDates(boolean showingDates) { this.showingDates = showingDates; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) @End public String cancel() { log.info(">cancel"); log.info("<cancel"); return "home"; } @Remove @Destroy @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void destroy() { log.info("> destory"); log.info("< destory"); } }