XPages Performance Master Class - Survive in the fast lane on the Autobahn (Engage 2014, Dev03)!

Post on 20-Aug-2015

420 views 0 download

Tags:

Transcript of XPages Performance Master Class - Survive in the fast lane on the Autobahn (Engage 2014, Dev03)!

XPages Performance Masterclass Survive in the fast lane on the Autobahn!

Howard Greenberg, TLCC Ulrich Krause, BCC GmbH

• Administrator /Developer since 1993

• Senior Software Architect at BCC, Germany

• OpenNTF Contributor

• IBM Champion 2011/2012/2013/2014

• Blog http://www.eknori.de

• Twitter @eknori

• Mail ulrich.krause@eknori.de

About: Ulrich Krause

• Notes/Domino developer, admin, instructor since 1993

• Before that was at IBM for 11 years in the PC Company

• Partner at TLCC, a provider of courses for Notes/Domino

– And lots of XPages courses!

– Some are even FREE!

• IBM Champion 2012/2013/2014

• Host a great monthly webinar series!

• Twitter @TLCCLtd

• Mail howardg@tlcc.com

About: Howard Greenberg

• What factors affect Performance?

• JSF Lifecycle

• Partial Update / Partial Execute

• Tools

• Coding Factors

– ViewNavigator vs. GetItemValue

– SSJS vs. Java

– Stringbuilder

• Questions???

Agenda

XPages Request

• The hardware used has a significant influence on performance. There are 3 key elements:

– CPU

– Main Memory

– Hard Disk

Hardware

• Latency

– Time taken for data transmission between multiple computers on a network

• Bandwidth

– Rate of transmission of data

• Greater Bandwidth + Lower Latency -------------------------------- = Better Connection

Network

• Hardware

• How many data requests / responses are transmitted

• How much data is transferred (size)

• Caching of resources

• How much CSJS runs

• Size / complexity of the CSS

• Complexity of the site structure

Client & Browser

• Browser / HTTP server

– Network latency – distance/time to server.

– Bandwidth – size of files.

– Browser limits on concurrent downloads • IE7 allows 2 downloads, IE8 allows 6

• HTTP Server / App Server

– HTTP Server JVM heap size & garbage collector

– CPU time, competition between threads, gives slower response times

– Threads, limited to 40 by default

Limiting factors on performance

• App Server / Domino context

– Read design elements from the NSF (XPage .class files, form structure, etc)

– Backend API calls may be expensive, especially for large data sets

– Design elements may be network requests

Limiting factors on performance

• Servlet / Lifecycle

– Restore control tree – file system read. Control tree locking – no concurrent access

– Rendered re-evaluated for every control for most phases

• Browser/Client JavaScript/Dojo

– Inline JavaScript blocks insertion of later HTML elements into the DOM tree

– Dojo does AJAX requests for .js files for dojo modules that are not loaded

Limiting factors on performance

• notes.ini

– HTTPJVMMaxHeapSizeSet=1

– HTTPJVMMaxHeapSize=256M • Should be set to ¼ of the available RAM

• Domino Administrator

– HTTP server Disable Logging

– HTTP server thread count defaults to 40

• link to IBM article

General Performance Options

• Debugging enabled in notes.ini ?

– JavaEnableDebug=1

– JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000

– JavascriptEnableDebug=1

General Performance Options (cont.)

• xsp.persistence.mode=

– Defines the persistence mode for the JSF pages • file: All the pages are persisted on disk

• fileex: All the pages are persisted on disk except the current one, which stays in memory

• <else>: All the pages stay in memory (tree mode)

Reducing Memory Utilization

• Groups many DOJO, CSS / JS files into a single file

– Less requests from the browser to the server

– Performance improvements on networks with high latency

– Enhanced performance parsing CSS / JS

– Fewer connections to the server

JavaScript/CSS Aggregation

On the Server: xsp.properties: xsp.resources.aggregate=true

JavaScript/CSS Aggregation

• XPagesPreload=1

• New Feature in Notes / Domino 8.5.3

• Works on Server and Client

• Java classes from the XPages runtime plug-ins loaded from a fixed list of runtime classes ( 435 in ND 8.5.3 )

– com.ibm.xsp.core, common utility, JS wrapper, FSF runtime classes

• Java classes referenced in *-faces.config.xml

– XPages control renderer, data sources, complex types

XPages PreLoad

• XPagesPreloadDB=Server!!Db.nsf/XPage.xsp,myLocalDb.nsf

• XPagesPreloadTrace=1 ( as of 9.0.1 )

• Works at the application level

• The application is loaded on the client / server startup into memory

– This happens even when the application is first opened in the browser

XPages PreLoad

• For each entry in the notes.ini variable, an XPage URL is generated and sent to the server

• The application is loaded, and the HTML generated

• The XPages runtime discards the HTML, but retains the application in memory

XPages PreLoad (cont.)

• applicationScope

– Are visible for all users of one application

– Expires some time after the last user used an applicationScope variable

– applicationScope variables are NOT persistent forever

• sessionScope

– Is valid through the session of the current user

– A user session expires after some time of inactivity

– Uses don't have access to the sessionScope variables of other users

Scoped Variables

• viewScope

– Is visible for views on the current page only.

– Useful for transporting a search query to a view.

• requestScope

– Is valid through one request of the current user.

– That includes refreshing of a page.

Scoped Variables (cont.)

Caching with Application Scope

JSF Life Cycle - Post

Restore View

•Restore component tree

•Events:

•afterRestoreView

Apply Request Values

•Copy data to Editable controls

Process Validations

•Validations

•Converters

Update Model Values

•Move values to data source

Invoke Application

•Application logic

•Events:

•onClientLoad (XPage, etc)

•on… events of button, etc.

Render Response

•Convert to HTML, etc.

•Events:

•beforeRenderReponse

•afterRenderResponse

Request

Response

Lifecycle1 XPage – Initial Page Load

Render Response

• Rendered property for id: label1

• Label property for id: label1

• Rendered property for id: inputText1

• Default value property for id: inputText1

• Rendered property for id: label2

• Rendered property for id: comboBox1

• values property for id: comboBox1

• values property for id: comboBox1

• Rendered property for id: computedField1

• Value property for id: computedField1

• Rendered property for id: computedField2

• Value property for id: computedField2

Lifecyle1 – Submit (Full Update) Restore View

Apply Request Values (8)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Process Validations (11)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Validation for inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Update Model Values (8)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Invoke Application (1)

•OnClick event for id: button1

Render Response (11)

•Rendered property for id: label1

•Label property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•values property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Value property for id: computedField1

•Rendered property for id: computedField2

•Value property for id: computedField2 39 SSJS Calls

When to Execute - # vs $

• # is Compute dynamically – Executed every time the page is rendered

– Use for values that are likely to change

• $ is Compute on Page Load – Executed when the page is first loaded

– Use for values that don't change

<xp:label id="label1">

<xp:this.value>

<![CDATA[#{javascript:return “My Label”;}]]>

</xp:this.value>

</xp:label>

Lifecyle2 – Submit (Full Update) - On Page Load

Restore View

Apply Request Values

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Process Validations (2)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Validation for inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Update Model Values

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Invoke Application (1)

•OnClick event for id: button1

Render Response (3)

•Rendered property for id: label1

•Label property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•values property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Value property for id: computedField1

•Rendered property for id: computedField2

•Value property for id: computedField2 6 SSJS Calls, saved 33

Changed all Rendered and Values (comboBox) to only compute on Page Load

But I need dynamic Rendering!

Options for dynamically computing the Rendered:

• Scoped variables

– Still get calculated but do the heavy lifting once and then read the scoped variable in the Rendered property

• DataContexts

– Compute a value at the Xpage or Panel level once

– Refer to the value using EL (much faster than SSJS)

• Can be thought of as global variables

• Value can be computed dynamically or on page load

– Warning: Computing dynamically has performance impact

• Can be scoped to any level that a data source can

– XPage, Custom Control or Panel

– Set a dataContext in a panel in a repeat control to avoid multiple references to a NotesDocument's item

• Can be referenced using EL

– Benefit: Not having to go through the SSJS parser

DataContext

• Be careful binding data context variables dynamically

– They will be recomputed multiple times, even when in partial execution mode and if they are not in use (six times!)

• Apply Request Values

• Process Validations

• Update Model Values

• Invoke Application

• Twice in Render Response!

• If computed on page load then only computed once on page load

• See Paul Withers blog entry to learn how to set a data context value via code

DataContext - Pitfall

• Partial Refresh (Update)

– Computes entire XPage, only sends back what is in the partial refresh id (refreshId)

• Partial Execution

– Only calculates what is in the area specified (execId)

Partial Refresh vs. Partial Execution?

Partial Refresh Demo - Results

Restore View

Apply Request Values (8)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Process Validations (11)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Validation for inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Update Model Values (8)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Invoke Application (1)

•OnClick event for id: button1

Render Response (2)

•Rendered property for id: label1

•Label property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•values property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Value property for id: computedField1

•Rendered property for id: computedField2

•Value property for id: computedField2 30 SSJS Calls, saved 9

Only Savings were here!

• Pros

– Reduced control processing in the render response phase

– Smaller response from server • Means reduced network usage

– Better UI experience • Rest of the page is still visible while waiting for a response

• Cons

– Controls like computed fields outside refresh area don’t refresh

– Be careful turning this on for a completed XPage (TEST!)

– Can only update one area (one id) • Workaround on Tim Tripcony blog here

Partial Refresh Pros and Cons

Partial Execution Demo - Results

Restore View

Apply Request Values (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Process Validations (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Validation for inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Update Model Values (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Invoke Application (1)

•OnClick event for id: button1

Render Response (12)

•Rendered property for id: label1

•Label property for id: label1

•Rendered property for id: inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•values property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Value property for id: computedField1

•Rendered property for id: computedField2

•Value property for id: computedField2

16 SSJS Calls Saved 13

• Pros

– Reduced processing in the 3 data-processing phases

• Cons

– Control with onClick event has to be inside the execId area

– Editable values outside of the executed area do not get submitted/updated (reset to default values)

– Existing XPages need analysis/testing before using this

• Current onclick events might refer to controls where the data is not submitted

– ExecMode available in 8.5.1

– Have to use source to enter ExecId (in 8.5, 9.0 has Designer UI)

Partial Execution Pros and Cons

Partial Refresh AND Execution Demo - Results

Restore View

Apply Request Values (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

•Rendered property for id: computedField2

Process Validations (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Validation for inputText1

•Default value property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Update Model Values (1)

•Rendered property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•Rendered property for id: comboBox1

•Rendered property for id: computedField1

•Rendered property for id: computedField2

Invoke Application (1)

•OnClick event for id: button1

Render Response (2)

•Rendered property for id: label1

•Label property for id: label1

•Rendered property for id: inputText1

•Rendered property for id: label2

•Rendered property for id: comboBox1

•values property for id: comboBox1

•values property for id: comboBox1

•Rendered property for id: computedField1

•Value property for id: computedField1

•Rendered property for id: computedField2

•Value property for id: computedField2

6 SSJS Calls, saved 33

Restore View Apply Request

Values Process

Validations

•No Validators get executed here!

Update Model Values

Invoke Application

Render Response

• All phases (1-6) occur

• Turns off all validators

• Converters continue to work

• Items in documents will be updated

disableValidators= true

Restore View Apply Request

Values Process

Validations Update Model

Values Invoke

Application Render

Response

• JSF Lifecycle processes only phases (1, 2, 6)

• No data processing

• Items in documents are not updated

• Onclick event handler scripts and render response calculations are performed

Immediate = true

• Loaded = true – Not in component tree or memory

• Loaded = false

– Control is not created

– Can never be rendered or accessed

– Saves memory too

Using the loaded Property

• Most properties, like CSS “style” are only computed in the RenderResponse phase

• Watch and minimize:

– Rendered property (when dynamic)

• Computed multiple times!

• Use dataContexts or scoped variables when able

• Use both Partial Refresh (Update) and Partial Execute when able

Life Cycle Performance Suggestions

• @DbLookup about 3-4 times slower than SSJS – res = @DbLookup(db,"CustomersByNameView",names[i], "phone");

vs. – doc = vw.getDocumentByKey(names[i], true);

res = doc.getItemValueString("phone");

• Five lookups repeated 100 times

– @DbLookup averaged about 1728ms

– getDocumentByKey averaged 510ms

• Other @Functions not tested

Watch Out for @DbLookup

• Use correct file type depending on content

– JPEG for complex and detailed images

– PNG/GIF for simple images, fonts, transparencies • Use the HTML <img> tag “width” and “height” attributes

• For faster HTML layout in the browser

– Size the image to size you intend to use • Resizing using html attributes height and width will delay the rendering

of your page

• Images larger than necessary will waste bandwidth

Images

• Use CSS Image Sprites

– If you have multiple small images, make a single larger image containing the smaller images

– Use CSS to display only the relevant subset image at a location in the page

– For semantically significant sprites, provide an accessibility “title” attribute (as sprites don't use the IMG “alt” attribute, but you still want to assist blind users)

– There's no specific XPages support for sprites, but they're used in the XPages OneIU themes

Image Sprites

43

CSS Image Sprite Sample

http://www.w3schools.com/css/tryit.asp?filename=trycss_sprites_img

• XPages based Application

– Runs on the Domino server or the Notes client

– An NSF needs to be installed on the server/Notes client

– A profiler jar file should be added to the JVM launch options

• Measures CPU performance and memory allocation

• Available from OpenNTF.org

– Free open source project • http://www.openntf.org/internal/home.nsf/project.xsp?action=openDoc

ument&name=XPages%20Toolbox

• Extended in 8.5.2 to support backend classes profiling

XPages Toolbox

XPages Toolbox

• Generate a heap dump of the JVM running in the HTTP task

– A button in the XPages profiler generates the heap dump

– From the Domino console • tell http xsp heapdump (triggers com.ibm.jvm.Dump.HeapDump())

• tell http xsp javadump (triggers com.ibm.jvm.Dump.JavaDump())

• Analyze the heap dump using the Eclipse memory analyzer

– http://www.eclipse.org/mat/

– http://www.ibm.com/developerworks/java/jdk/tools/dtfj.html

XPages Toolbox

Heapdump / Javadump Analyzer

• Print statements

– In rendered/visible computations to see how often executed • print("panel2 evaluating rendered property");

– In the XPages root control events:

• before/afterPageLoad, afterRestoreView, before/afterRenderResponse

– Custom control root events:

• before/afterPageLoad

– In the document data source events:

• queryNewDocument, postSaveDocument, etc.

• Task Manager and/or Process Explorer

– Shows CPU usage & process memory usage as it happens

More Tools

• Browser developer tools

– for watching network transactions, partial updates, response times

– BROWSER: Firebug, Developer Tools

– XPiNC: FirebugLite from ExtLib

• Java / Javascript Debugging

– Degrades performance but can inspect objects

• Use the Eclipse Java debugger

– In Domino\notes.ini add these 2 options: • JavaEnableDebug=1

• JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000

More Tools

Optimisation – Step by Step

• Creates a NotesDocumentCollection

• Creates a JSON String from the documents in the collection

Step1: Original Code from sample

Step1: Result

• Like Step1, but UNID is written to an item when document is saved

Step 2: Read UNID from item

Step2: Result

• Instead of reading the values from the document‘s items, we store the JSON data when the document is saved

Step3: Create JSON in document

Step 3: Result

Step 4: Create JSON in a view

Step 4: Result

• To concat two strings, you only need a +

• Each operation creates a new string object, adds the new string to the object. Discards the object

• The longer the string, the longer it takes .

• Use the + with 2 or 3 strings

• Use a StringBuilder if you handle tons of data.

StringBuilder vs String.concat

• Tons of data Use StringBuilder

– + und concat are easy to use, but not always the best way

StringBuilder vs String.concat

Step 5: StringBuilder

Step 5: Result

Step 6: JAVA …

Xpage SSJS Code

Java Code

Step 6: Result

Q & A