Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
488 views

Tuning JSF Applications - J-Spring 2008

This document discusses how to improve the performance of JSF applications. It begins with an introduction to JSF and outlines common performance pitfalls related to session size, CPU usage, and bandwidth. It then discusses profiling JSF applications to identify bottlenecks and recommends various configuration options and design patterns to improve performance, such as using server-side state saving, limiting the number of components, and leveraging caching.

Uploaded by

npsakthi
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
488 views

Tuning JSF Applications - J-Spring 2008

This document discusses how to improve the performance of JSF applications. It begins with an introduction to JSF and outlines common performance pitfalls related to session size, CPU usage, and bandwidth. It then discusses profiling JSF applications to identify bottlenecks and recommends various configuration options and design patterns to improve performance, such as using server-side state saving, limiting the number of components, and leveraging caching.

Uploaded by

npsakthi
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

Tuning JSF applications

Session size matters

Eelco Klaver (eklaver@econsulting.nl)


LinkedIn: http://www.linkedin.com/in/eklaver Member of Know IT knowledge network
DOING ENTERPRISE JAVA RIGHT FROM THE START!

And finally just one tiny little thin Java bean, Mr. Creosote?
First JSF production experience
Pilot with 30 users went great After 3 months a big media event was organized to train first 80 future users Dedicated hardware consisted of 2 production like machines (just to be sure) each serving 40 users Memory usage grew rapidly

Until it finally exploded


after 30 minutes already

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Goal of this presentation


Demystify the JSF performance pitfalls and discuss ways to measure and improve the scalability of JSF applications After the session you will understand the performance implications of conguration options and design decisions in JSF Prerequisites
Basic JSF knowledge is required to fully understand this session

Scope
Focus on JSF specific issues Application logic optimization and database tuning is out of scope
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Contents
Introduction The essentials of JSF
JSF life cycle Component tree and view state saving

JSF performance pitfalls


Session size, CPU, bandwidth

Profiling JSF applications


Memory profiling Performance measuring of different phases

Improving performance
Performance tweaks Application guidelines

Conclusion
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Introduction

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Introduction
JSF is a relatively new technology, although
JSF JSF JSF JSF 1.0 released in Feb 2004 1.1 released in May 2004 1.2 released in Nov 2006 currently defacto standard for web applications

Advantages over other frameworks like ability to create reusable components maintaining own state but little is known about performance implications
Memory usage Bandwidth CPU usage

Why bother?
DOING ENTERPRISE JAVA RIGHT FROM THE START!

The essentials of JSF

DOING ENTERPRISE JAVA RIGHT FROM THE START!

JSF: Component-based architecture


Reusable user interface components
Each UI Component maintains own state It represents attributes, behaviors and events Separation between component behavior and rendering Converters and validators can be registered with components Examples include Label, Text-Field, Form, Checkbox, etc.
UIViewRoot HTMLForm HTMLPanelGrid HTMLOutputLabel HTMLInputText HTMLOutputLabel HTMLInputSecret HTMLCommandButton
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Component tree

JSF: Lifecycle
Response complete

Send Request

Restore View

Apply Request Values

Process Events

Conversion and Validation

Response complete

Process Events

Render Response

Client
Response complete

Server
Response complete

Update Model

Render Page

Render Response

Process Events

Invoke Application

Process Events

Render Response
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Render Response

JSF: State saving (1)


All view related state in JSF is saved and restored
Component tree structure Component attributes

Components save their own state


saveState restoreState

Example
public Object saveState(FacesContextcontext) { Object values[] = new Object[3]; values[0] = super.saveState(context); values[1] = this.title; values[2] = this.text; return ((Object) (values)); }
DOING ENTERPRISE JAVA RIGHT FROM THE START!

JSF: State saving (2)


Methods of state saving is configurable
Server side - state is stored in HTTP session Client side - state is serialized and stored in hidden input param Server side Low CPU usage Low bandwidth Easier integration with Ajax Security Session memory per user Session memory old views Clustering needs session sync. More difficult to test Client side Low server memory Easier to cluster Ability to restart server No concurrency issues (Browser back button) Higher CPU usage Higher bandwidth Higher client memory usage Security -> Encryption needed

DOING ENTERPRISE JAVA RIGHT FROM THE START!

JSF Performance pitfalls

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Bottlenecks (1/2)
Memory
Session size caused by server side state saving Session scoped view beans

CPU
State saving and rendering due to high number of components

Bandwidth
Especially with client side state saving

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Bottlenecks (2/2)
Quiz question
View state size? Time to process? Total page size?

Hints
Client side state saving Multiple forms No compression Encryption Role-based menu

Answer
Memory: 300kB view state CPU: 550ms Bandwidth: 1,5MB page size
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Profiling JSF applications

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Locating performance problems


Locate source of the problem
Client, server or network

Determine lifecycle phase containing performance issues


MyFaces: log4j.logger.org.apache.myfaces.lifecycle=DEBUG
2007-10-08 2007-10-08 2007-10-08 2007-10-08 2007-10-08 20:18:25,846 DEBUG - entering RESTORE_VIEW(1) 20:18:25,856 DEBUG - exiting RESTORE_VIEW(1) 20:18:25,856 DEBUG - entering APPLY_REQUEST_VALUES(2) 20:18:27,618 DEBUG - entering RENDER_RESPONSE(6) 20:18:27,799 DEBUG - exiting RENDER_RESPONSE(6)

JSF PhaseListener combined with JAMon

Determine end-to-end time


JMeter, also for regression stress testing

Network = Total - Server

DOING ENTERPRISE JAVA RIGHT FROM THE START!

The Java Application Monitor (JAMon)


The Java Application Monitor (JAMon) is a free, open source, easy to use, high performance, thread safe, Java API that allows developers to easily monitor applications in development, test and production. Includes a web application for viewing reports and controlling behavior Example
Monitor monitor = MonitorFactory.start(myPage.jsp); // Code to be monitored monitor.stop();

DOING ENTERPRISE JAVA RIGHT FROM THE START!

JAMon performance listener (1/2)


Example: PerformancePhaseListener
public class PerformancePhaseListener implements PhaseListener { public void beforePhase(PhaseEvent phaseEvent) { String phaseName = phases.get(phaseEvent.getPhaseId()); HttpServletRequest request = getRequest(phaseEvent); Monitor monitor = MonitorFactory.start(phaseName + "." + request.getRequestURI()); getRequest(phaseEvent).setAttribute("monitor", monitor); } public void afterPhase(PhaseEvent phaseEvent) { Monitor monitor = (Monitor)getRequest(phaseEvent) .getAttribute("monitor"); monitor.stop(); } public PhaseId getPhaseId() {return PhaseId.ANY_PHASE;}
DOING ENTERPRISE JAVA RIGHT FROM THE START!

JAMon performance listener (2/2)


Example: JAMon output

Note: Render response phase includes lazy loading


DOING ENTERPRISE JAVA RIGHT FROM THE START!

JAMon view state listener


Example: ViewStatePhaseListener
public class ViewStatePhaseListener implements PhaseListener { public void beforePhase(PhaseEvent phaseEvent) { LRUMap viewStateMap = getViewStateMap(phaseEvent); monitor = MonitorFactory.getMonitor(Total view state", "KB"); monitor.add(sizeof(viewStateMap)/1024); Object viewState = getViewState(phaseEvent); monitor = MonitorFactory.getMonitor("View state" + "." + request.getRequestURI(), "KB"); monitor.add(sizeof(viewState)/1024); } public PhaseId getPhaseId() {return PhaseId.RESTORE_VIEW;}

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Facelets debug component


UI Debug
Display helpful information about the JSF component tree and scoped variables in browser

Example
<ui:debug hotkey="V"/>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Improving performance

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance improvements
Possibilities depend on framework used
MyFaces JSF RI 1.1/1.2 Ajax4JSF Facelets

Configuration parameters
State serialization Number of views

Application design principles


Managed bean scope Number of components Caching Individual components chosen
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (1/7)


Always use server side state saving
Although server memory decreases, CPU increases significantly in Phase 1 and 6 because of de/serialization and possibly encryption Bandwidth usage increases as page size increases because view state is replicated in hidden field for each form on the page!

Example: configure in web.xml


<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (2/7)


Comparison: client v.s. server side state saving (JSF RI)
Page (kB) Phase 1 (ms) Phase 6 (ms) Total (ms) Client Client Comp. Client Enc. Client C+E Server 214 51 214 51 9 30 63 63 58 2 48 46 77 48 37 78 109 140 106 39

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (3/7)


CPU usage: client v.s. server side serialization (MyFaces)

Source: ApacheCon 2006


DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (4/7)


CPU usage: client state saving (MyFaces)

Source: ApacheCon 2006


DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (5/7)


Disable state serialization and compression
State serialization and compression of the view state has a major impact on the CPU usage in phase 1 and 6.

Example: configure in web.xml


MyFaces:
<context-param> <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name> <param-value>false</param-value> </context-param>

JSF RI 1.2: com.sun.faces.serializeServerState [false] com.sun.faces.compressViewState [true]


DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (6/7)


Server side state saving options (MyFaces)

Source: ApacheCon 2006


DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: State saving (7/7)


Limit the number of active views per session
The default of 15 logical and 15 views in session requires 10 MB per user with an average view state of 50 kB.

Example: configure in web.xml


JSF RI 1.2:
<context-param> <param-name>com.sun.faces.numberOfViewsInSession</param-name> <param-value>5</param-value> </context-param> <context-param> <param-name>com.sun.faces.numberOfLogicalViews</param-name> <param-value>10</param-value> </context-param>

MyFaces: org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION

Note: not configurable with latest Ajax4JSF framework


DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Configuration: Ajax4JSF (1/1)


Configure Ajax filter to only parse Ajax responses or even disable parsing
Ajax4JSF Filter will parse generated (X)HTML and converts it to valid XHTML. Disabling will accelaterate processing.

Example
<filter> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.FastFilter</filter-class> <filter-class>org.ajax4jsf.webapp.TidyFilter</filter-class> <init-param> <param-name>forceparser</param-name> <param-value>false</param-value> </init-param> </filter>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Bean scope (1/1)


Make managed beans request scoped
Session scoped beans will increase the memory usage as session size grows for each user

Example: master/details view


<t:saveState value="#{signaalSearchView.signalen}/> <t:dataTable value="#{signaalSearchView.signalen}" var="signaal"> <t:column> <f:facet name="header"> <h:outputText value="#{msgSignalen['signaal.header.nummer']}" /> </f:facet> <t:commandLink action="#{signaalTonenTabbedPaneView.show}"> <h:outputText value="#{signaal.id}" /> <f:setPropertyActionListener value="#{signaal.id}" target="#{signaalTonenTabbedPaneView.signaalId}" /> </t:commandLink> </t:column>
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Component-tree (1/3)


Use c:if instead of visibleOnUserRole and rendered
The attributes visibleOnUserRole and rendered still cause component to appear in component tree, increasing memory and CPU usage Note: this only works for values known at compile time

Example: role-based menu item


<t:commandLink action=#{action}" visibleOnUserRole="#{roles}"> <c:if test=#{ec:isUserInRole(roles)}"> <t:graphicImageaction=#{action}" > <t:commandLink value=/wc.gif rendered="#{not <t:graphicImage value="#{(not open and not disabled}"/> disabled?'/wc.gif': <t:graphicImage value=/wo.gif and not disabled?'/wo.gif': (open rendered="#{openopen not disabled}"/> (not and and disabled?'/gc.gif': <t:graphicImage value=/gc.gif '/go.gif')))}"/> rendered="#{not open and disabled}"/> #{name} <t:graphicImage value=/go.gif </t:commandLink> rendered="#{open and disabled}"/> </c:if> #{name} </t:commandLink>
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Component-tree (2/3)


Use ui:repeat instead of c:forEach
The c:forEach creates component in component tree for every object in the list, increasing memory and CPU usage Note: this only works for values known at compile time

Example: list of shopping items


<c:forEach var=item items=#{itemsView.items} <ui:repeat values=#{itemsView.items} <t:commandLink action="#{action}"> #{name} </t:commandLink> </c:forEach> </ui:repeat>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Component-tree (3/3)


Prevent multiple components per mode or role
Although not rendered simultaneously, both components will still be in the component tree using memory and CPU in phase 1 and 6 Use extended components instead

Example: page with read- and edit mode


<h:outputText value="#{messages['label.email']}"/> <h:panelGroup> <t:inputText value="#{myView.email} size="20" maxlength="128" <h:outputText value="#{myView.email}" displayValueOnly="#{myView.readMode}"> rendered="#{myView.readMode}"/> <t:validateEmail /> <h:inputText value="#{myView.email} size="20" maxlength="128 </t:inputText> rendered="#{not myView.readMode}"> </h:panelGroup> <t:validateEmail /> </h:inputText> </h:panelGroup>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Caching (1/1)


Cache list items in converters
Converters are called multiple times within request phase 3

Example: make converter a view bean and give it scope


<managed-bean> <managed-bean-name>rubriceringConverter</managed-bean-name> <managed-bean-class>RubriceringConverter</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean> <t:selectOneListbox converter="#{rubriceringConverter}"> <t:selectItems value="#{rubriceringConverter.rubriceringen}" var="rubricering" itemValue="#{rubricering}" itemLabel="#{rubricering.naam}"/> </t:selectOneListbox>
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Performance tips Guidelines: Evil components (1/1)


Use only stable component libraries
Very easy to add external components, like JBoss RichFaces component library with calendar, tooltip, modalpanel, but introduces performance problems and memory leak in IE6.

Example: calendar component


<rich:calendar value="#{projectView.startDate} <t:inputCalendar value="#{projectView.startDatum}" renderAsPopup="true" enableManualInput="true" popupDateFormat="dd-MM-yyyy"/> popup="true" direction="auto" datePattern="dd-MM-yyyy/>

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Conclusion

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Summary
JSF performance pitfalls
Memory consumption CPU usage Bandwidth

First profile then optimize JSF and state saving


Always use server side state saving Configure number of states to be stored

Application design guidelines


Use request-scoped view beans Decrease number of components Use caching in converters Choose components wisely
DOING ENTERPRISE JAVA RIGHT FROM THE START!

Discussion
Is JSF still a good choice? Yes,
Clean separation between component state/behavior and rendering Easy to use Standard With appropriate measures it can still perform right

Future enhancement might be to only save state thats different from default:
Facelets XHTML defines component tree with default values This tree is updated with delta state

DOING ENTERPRISE JAVA RIGHT FROM THE START!

Questions

DOING ENTERPRISE JAVA RIGHT FROM THE START!

References
Tools
JMeter - http://jakarta.apache.org/jmeter/ JAMon - http://jamonapi.sourceforge.net/ YSlow - https://addons.mozilla.org/en-US/firefox/addon/5369

Technologies
JBoss Serialization - http://labs.jboss.com/serialization/ Facelets - https://facelets.dev.java.net

Books
High Performance Web Sites, Steve Souders, http://developer.yahoo.com/performance/

DOING ENTERPRISE JAVA RIGHT FROM THE START!

You might also like