Using XPages out of the box lets you build good looking and well performing applications. However, as XPage applications become bigger and more complex, performance can become an issue and, if it comes to scalability and speed optimization, there are a couple of things to take into consideration.
Learn how to use partial refresh and partial execution mode and how to monitor its execution using a JSF LifeCycle monitor to avoid multiple re-calculation of controls. We will show tools that can allow you to profile your code, readily available from OpenNTF, along with a demonstration of how to use them to improve the speed of your code.
Still writing SSJS and encounter a significant slow down when using Script Libraries? See, how you can improve the speed of your application using JAVA instead of JS, JSON and even @formulas.
Unleash Your Potential - Namagunga Girls Coding Club
Life In The FastLane: Full Speed XPages
1. Life In The Fast Lane
Full Speed XPages
March , 21. – 22. 2013
Faculty Club, Leuven, Belgium
Ulrich Krause, BCC Unternehmensberatung GmbH
Matthew Fyleman, We4IT
2. About: Matthew Fyleman
Lotus Notes/Domino Developer since 1993
Senior Developer at We4IT GmbH
Recently focused entirely on XPages
development
Working on We4IT's XPages framework
Also on Offline capabilities for We4IT’s mobile
framework
3. About: Ulrich Krause
Lotus Notes/Domino Developer since 1993
Senior Software Architect at BCC
OpenNTF Contributor
OpenNTF Board of Directors
IBM Champion 2011/2012/2013
Blog http://www.eknori.de
Notes Forum (http://www.atnotes.de)
4. Agenda
Performance, what factors affect it?
Java vs. JavaScript
Looping through Documents, ViewNavigator vs.
GetNextDocument
Stringbuilder vs. Concat (+)
JSF Lifecycle Listener
Partial Update / Partial Execute
Variable Resolver
Tools
6. Hardware
The hardware used has a significant influence on performance.
There are 3 key elements:
• CPU
• Main Memory
• Hard Disk
7. Hardware
CPU
• Cores / Clock / Cache
• Poor response time
Main Memory
• Limit defined by the operating system
• Scalability
Weak CPU AND Low Memory
• Poor overall performance
• Poor response times
• Server "hangs"
8. Network
Latency
• Time taken for data transmission between multiple computers on a
network
Bandwidth
• Rate of transmission of data
Greater Bandwidth
+ Lower Latency
--------------------------------
= Better Connection
9. Client & Browser
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
10. Limiting factors on performance
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 memory allocation (heap size) & garbage collector
• CPU time, competition between threads, gives slower response times
• Threads, limited to 40 by default, configurable in Domino Administrator
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.
11. 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
12. General Performance Options
notes.ini
• HTTPJVMMaxHeapSizeSet=1
• HTTPJVMMaxHeapSize=256M
• Should be set to ¼ of the available RAM
Domino Administrator
• HTTP server "Enable logging to" disabled
• HTTP server thread count – defaults to 40
Remember, enabling the debugger affects performance
• JavaEnableDebug=1
• JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000
• JavascriptEnableDebug=1 ( Version 9 )
13. Reducing Memory Utilization
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)
14. XPages Design Optimizations
Simple actions vs links or button with window.location JS
Reduce server phase processing
• Use partial update where possible
• Use partial execute where possible
• Use disableValidators & immediate event
Minimize work in rendered / visible computations
• Use variable resolver
Repeats & Views
• Use viewEntry.getColumnValue instead of viewEntry.getDocument.getColumn
• Use Domino View data source dataCache property where possible
15. XPages Design Optimizations
Load-time vs Runtime
• Using loaded vs rendered
• ExtLib Dynamic Content
– allows partial re-loading so more use of load-time optimizations
Loading resources in the browser
• CSS & browser JS
– extract to separate files. Minify & compress files
• Images
– use correct size & format. Use CSS Image Sprites as possible
16. JavaScript/CSS Aggregation
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
On the Server: xsp.properties:
xsp.resources.aggregate=true
18. XPages Pre-Load
XPagesPreload=1
New Feature in Notes / Domino 8.5.3
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
19. XPages Pre-Load
• XPagesPreloadDB=Server!!Db.nsf/XPage.xsp, myLocalDb.nsf
• 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
• 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
20. Scoped Variables
applicationScope
• Are visible for all users of one application. Expires some time after the last user
used an applicationScope variable.
That means 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.
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.
23. XPages Lifecycle Listener
What happens in each phase of the JSF lifecycle?
Ulrich Krause: http://openntf.org/XSnippets.nsf/snippet.xsp?id=a-simple-lifecyclelistener-
25. When to Execute - # vs $
#
• Executed every time the page is rendered
• Use for values that are likely to change
$
• Executed when the page is first loaded
• Use for values that don't change
26. DataContext
dataContexts can be thought of as global variables
dataContext's value can be computed dynamically or on page
load
• So you can use ${javascript:@Today()} and run it once rather than running
a function each time.
dataContexts can be scoped to any level that datasources can
• XPage, Custom Control or Panel
• you can set a dataContext in a panel in a repeat control, to avoid multiple
references to a NotesDocument's item
dataContexts are referenced using EL
• So at no point in the references do you run SSJS, so it's not having to go
through the SSJS parser
27. DataContext - Pitfall
Issue with data context variables if they are bound dynamically.
• They will be recomputed again and again, even when in Partial Execution
mode and if they are not in use (http://hasselba.ch/blog/?p=1112)
29. Partial Refresh / Update (Pro)
Reduced control processing in the render response phase
• Means less work on the server
– render response is the most intensive phase
Smaller response from server.
• means reduced network usage
Better browser experience
• rest of the page is still visible while waiting for a response
• inserting small sections into the page is much faster than reloading a full page.
30. Partial Refresh / Update (Cons)
Dependancy outside of the partial update area
• Other areas of the control tree are not processed,so any SSJS scripts in those
other controls will not be run.
• Enabling Partial Update where it was previously full update may lead to
functional problems
Only one area may be partial updated by default
• In CSJS you can schedule later partial updates of related areas, but any
concurrent requests will wait for exclusive access to the server-side control
tree before processing on the server
http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-
84B6VP
31. Partial Execution
Reduced control processing in the 3 data-processing phases
• Means less work on the server, faster response times
Dependancy on Edit Box values outside of the exec area
• Submitted values from Edit Boxes and/or other input controls in other areas of
the control tree are not processed, so any control values and document fields
in those other areas will not be updated. Enabling Partial Exec where it was
previously full execution may lead to functional problems where values are
out-of date in the onclick script or in the redisplayed page.
onclick Event Handler must be in the exec area
• The applyRequestValues phase prepares for the invokeApplication phase.The
onclick simple action or SSJS script won't occur if outside the partial exec area
32. Partial Execution
execMode only added in 8.5.1 (not in 8.5.0)
execId slightly difficult to select in Designer
• Select your button, in the Outline view, toggle open the button, select the child
Event Handler control, then set the execId property on the Event Handler.
• [Better UI proposed in Notes/Domino Next – in the Events tab]
33. disableValidators / immediate
disableValidators
• JSF life cycle through all phases (1-6)
• But requests will not validate the data
• Converters continue to work.
• Items in documents will be updated
• Sven Hasselbach - "Disable all validators at once" (
http://hasselba.ch/blog/?p=1106)
• Immediate
• 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
34. Minimize work in rendered / visible computation
Most properties, like CSS “style” are only computed in the
renderResponse
Edit Box and input “value” properties are used in Data Processing
phases & renderResponse
Data Source properties are computed during renderResponse &
results are cached for the next request's Data Processing &
invokeApplication phases
35. Minimize work in rendered / visible computation
The rendered property is computed in all 5 lifecycle phases
Avoid re-computing values in every rendered property
• @DbLookup, @DbColumn, getDocumentByKey
• In the rendered property, save the computed boolean to a viewScope
variable
36. Using loaded vs rendered
Loaded
• is only computed once in the createView phase
• not re-computed in the 5 usual phases
• false means the control is not created. So it can never be rendered.
• true means the control is added to the control tree.
• You can still compute rendered when loaded evaluates to true.
Compute the loaded property on conditions
• where you could compute the rendered property and save it to the view
scope
• it would never need to be recomputed for the rest of the interaction with
this page
37. Images
Use correct file type depending on content
• JPEG for complexed 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
38. CSS Image Sprites
Use CSS Image Sprites
• If you have multiple small images, make a single larger image containing
the smaller images
• And use CSS to display just the relevant subset image at a location in the
page
• For semantically significant sprites, provide an accessibility “title” attribut
(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
40. XPages Toolbox
XPages based Application
• Runs on the Domino server or the Notes client
• An NSF needs to be installed on the Domino server/Notes client
• A profiler jar file should be added to the JVM launch options
Measures the CPU performance and the memory allocation
Available from OpenNTF.org
• Free open source project
• Search for “XPages Toolbox”
Extended in 8.5.2 to support Backend classes profiling
http://www.openntf.org/internal/home.nsf/project.xsp?action=openDocument&name=XPages%20Toolbox
42. 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
44. More Tools
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
• Heap memory usage will be a subset of process memory, but heap dumps are
only a snapshot
45. 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, step into code.
• Use the Eclipse Java debugger.
• In Dominonotes.ini add these 2 options:
• JavaEnableDebug=1
• JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000
47. XAgent – SSJS
Get all „Contacts“ into a NotesDocumentCollection, loop the collection and build the
JSON by reading the values from items in the document
49. XAgent – SSJS – UNID from Item
Get all „Contacts“ into a NotesDocumentCollection, loop the collection and build the
JSON by reading the values from items in the document. Also UNID is stored in
document
51. XAgent – SSJS - SingleItem
Get all „Contacts“ into a NotesDocumentCollection, loop the collection and get the
JSON from an item on the document. The JSON is calculated on document save
55. StringBuilder vs String.concat
Concatenation of Strings is very easy in Java - all you need is a '+‘
Each time you append something via '+' (String.concat()) a new
String is created, the old stuff is copied, the new stuff is
appended, and the old String is thrown away.
The bigger the String gets the longer it takes - there is more to
copy and more garbage is produced.
Accordingly to Arno Unkrig the optimal strategy is to use
String.concat() for 2 or 3 operands, and StringBuilder for 4 or
more operands
String text= System.out.println("x:"+x+" y:"+y);
"line 1n"+
"line 2n"+
"line 3";
56. StringBuilder vs String.concat
When to use StringBuilder over '+' (String.concat()) ?
• use StringBuilder whenever you assemble a String in a loop
• Just keep in mind that '+' isn't always a good idea
http://kaioa.com/node/59
57. XAgent – SSJS – ViewNavigator + StringBuilder
loop thru a view and get the JSON from a view column. Use a StringBuilder to concat
the JSON
61. Themes
Single Document Containing References to all your CSS Resources
• resource sections reference the CSS files used
• control section define what CSS classes are applied to specific controls
XML Based and Easy To Learn
• creating a new theme document prefills sample content
Can Extend Other Themes
• <theme extends="webstandard">
• will automatically include all the resource and control definitions from that
theme built-in themes
• webstandard, notes, oneUI
62. Themes
Create your own themes from scratch.
Creating a theme that extends from the webstandard or another
supplied theme will include extra stylesheets and styles that you
might not need.
Be prepared to spend more time writing css though
Change the server page persistence setting to keep the current page in memory. Strictly speaking, keeping all pages in memory provides the best performance, but it tends to be downright wasteful of memory. When only the current page is kept in memory, as a user navigates from page to page (as opposed to firing events against the page they're already on... even if it's a full refresh event), it serializes the state of the previous page to disk. If a subsequent event is fired against that previous page, then that page's state is retrieved from disk and loaded back into memory. But this scenario only occurs if the application loads a new page in a new window or tab, and the user later switches back to the original window and interacts with it again. In typical navigation scenarios, once the user has opened a new page, the previous page instance no longer exists... even if they navigate back to the same page again, it's a new instance of that page. Hence, keeping all pages in memory essentially guarantees at least a temporary memory leak. All of that storage is eventually released, of course, but in the meantime the server is consuming memory it will never need again that would be better served storing whatever you're explicitly caching in scope variables.
JavaScript/CSS Aggregation feature For performance reasons, the XPages runtime now features a new option that dynamically aggregates multiple Dojo modules, or multiple CSSs into a single file. This results in the following performance improvements:a decrease in requests sent from the browser to the server an increase in user performance, particularly in the context of networks with high latency an increase in the speed of JS/CSS parsing from the browser the freeing up of server connections to fulfill other requests As an extreme example of the saving, let's say the XPages Extension Library is using the page DWA_ListView.xsp. Without the aggregator enabled, 82 requests are made to the server. With the aggregator enabled, the count decreases to 6 requests, including the Ajax request that gets the data. Also, a test run on processing time might see changes from ~4 sec to ~800 ms. To allow you to actvate this option, XPages now feature a new runtime option, which can be set in xsp.properties (database or server level). This option is xsp.resources.aggregate=true It can also be set in Domino Designer from the Application Properties - XPages tab by checking the Use runtime optimized JavaScript and CCS resources option.
XPages Preload options New options designed to improve the startup performance of XPages applications have been added to this release. A preference can be set that preloads the XPages runtime on the Domino server and Notes client. Additionally, specific XPages applications may also be preloaded. The preferences are set as entries in the NOTES.INI file and have the following form: XPagesPreload=1 XPagesPreloadDB=myServer!!myDb.nsf/myXPage.xsp,myLocalDb.nsf/test.xsp The XPagesPreload entry causes an extensive list of XPages runtime Java classes to be preloaded, so they are available in memory when an application is opened by a user. The XPagesPreloadDB preference lets a comma separated list of applications be specified, with or without a specific XPage extension. Again, any required classes are loaded when the server or client starts up and are thus available as soon as any declared application is accessed by a user. The benefit of this may be more evident when running in remote mode on the Notes client, i.e. the XPages is running on the client but the application itself resides on a remote server. In this instance, the Java classes in the application (XPages, custom controls) need to be loaded across the network in order to be executed in the local XPD web container. Preloading such applications produces more responsive initial user experience.
First and foremost, become intimately familiar with the so-called "scope variables". The nature and use of these are documented in detail elsewhere, so I won't belabor that here. But the better you understand what information is appropriate to store in each scope - and that you can store complex object structures, not just "string-to-string" mapping - and the more you take advantage of this, the faster the application's response will be. This is because you're limiting disk I/O as much as possible... the more frequently the application can just pull whatever data the user is requesting from RAM, instead of querying the database every time, the faster the application will be. This is why you want lots and lots of RAM. :) Of course, you don't want to be gratuitous with your memory storage, which is why it's crucial to understand which scope is appropriate for which type of data... when you get the hang of this, Domino will clean up these memory caches for you automatically. If you find that you're running out of memory, but you're confident your scope storage is reasonably optimized, tweak the application properties to clear the application scope periodically. The higher the frequency you set, the more you can cache in all the scopes without bursting the heap... but if you find you're needing to set this to a frequency of less than an hour, revisit what you're actually storing, because it's probably out of control.
Wherever possible, change your expressions from dynamic bindings to page load bindings. This is just a fancy way of saying that ${database.title} is always better than #{database.title}. The $ means that the expression is only calculated once per page instance... # means it's recalculated as often as needed - sometimes several times within the same request, depending upon what value is bound to the expression. So obviously you can't just change all your expressions to $... input controls bound to form items, for instance, should remain #. But if you have computed text displaying the application's title (as in the above example), that value is obviously unlikely to change during any given page instance, so change it to a $ expression, and then the server only has to evaluate it once. Combine this optimization with thorough scope caching, and it's easy to see how this can really speed up page load times and event execution response. This gets particularly noticeable when dealing with repeat controls: each time a user navigates to the next page of a repeat, if that repeat's value is a # binding, it has to recalculate that value... change it to a $, and it only loads the collection once. Even if the event the user triggered has nothing to do with the repeat, the server has to recalculate all # bindings, so if the repeat's value is a #, it still has to pull the collection again even though the user wasn't explicitly interacting with the repeat.
will tend to see out-of-date values. To see up-to-date but not-converted values use: var editBox1 = getComponent('editBox1'); var value = editBox1.getSubmittedValue(); if( null == value ) value = editBox1.getValue();