ShowTable of Contents
A collection of tipps for optimizing memory usage and performance for a XPage application.
General tips
- Use Domino 8.5.3 and enable the application setting for dynamic resource aggregation. This makes a HUGE difference.
- Add RAM to the server. The more RAM, the better. RAM is more important than CPU speed.
- Set notes.ini variable HTTPJVMMaxHeapSize to the fourth of the RAM (for example 2048M with 8GB RAM).
- If the server has a SSD disk, store the Domino program files on it.
- Use scoped variables (see below).
- Change server page persistence to "keep current page in memory" (application properties).
- In complex applications, try to move code to real Java classes instead of SSJS.
- Use EL instead of SSJS when possible.
- Change SSJS to "compute on page load" instead of "compute dynamically" where possible.
- Use fast view navigation using ViewNavigator Cache, see this article
for details.
Example for using EL instead of SSJS:
SSJS:
"#{javascript:return '/' + database.getFilePath() + '/images/' + currentDocument.getUniversalID() + '/$FILE/' currentDocument.getItemValueString('thumbnail');}"
The same in EL:
"/#{database.filePath}/images/#{currentDocument.universalID}/$FILE/#{currentDocument.thumbnail}"
Taken from Tim Tripcony
and Steve Castledine.
See also: Blog post of Mark Gargan: http://xpagesblog.com/xpages-blog/2009/8/10/writing-efficient-scalable-xpages.html
Increasing the possible workload of the server
XPages are using Java in the background, and the amount of memory Java can consume in the Domino server is limited by the HTTPJavaMaxHeapSize notes.ini parameter.
Check the technote at http://www-01.ibm.com/support/docview.wss?uid=swg21377202
for the latest recommendations and default values.
Set on the server console via
set configuration HTTPJavaMaxHeapSize=512M
Storing large amount of data in a scoped variable
Prefer java objects instead of javascript objects, for example use a java.lang.hashMap instead of a JavaScript array.
Doesn't matter for small amounts of data, only if you want to store many values.
Use partial refresh
If you change something on your page, use a partial refresh instead of a full refresh since partial refreshes only need to process a subset of the JSF tree and are therefore faster.
JavaScript variables
In 8.5.0 think about setting your variables to null when you don't need them anymore.
It is planned in 8.5.1 to have a setting so that all variables are cleared automatically after the lifecycle of a request.
Synchronized functions and caching
Matt White wrote about an interesting technique to optimize performance for frequently used functions, see the full post here: http://mattwhite.me/blog/2009/9/14/on-synchronization-in-xpages.html
In a nutshell: you can mark a block of code as 'synchronized' which means that it is not allowed to run concurrently when mutiple clients are doing the same.
A synchronized function is ideal to compute expensive stuff and cache it.
Here an example an example function which computes something expensive and caches the result. If the result is already in the cache, it is returned immediately.
A cached result expires after some time.
function getExpensiveResult(){
synchronized(applicationScope) {
if(isCacheInvalid("example_key", 600)) {
result = // do expensive computation of something, like iterating through a view or so
applicationScope.put("example_key", result);
}
}
return applicationScope.get("example_key");
}
/**
A generic caching mechanism for each key will check to see if it is 'n' seconds
since it was last updated. Use for things that change relatively infrequently
*/
function isCacheInvalid(key, cacheInterval){
var currentTime = new Date().getTime();
if (!applicationScope.containsKey(key + "_time")){
applicationScope.put(key + "_time", currentTime);
return true;
}
var diffInSecs = Math.ceil((currentTime - applicationScope.get(key + "_time")) / 1000);
if (diffInSecs < cacheInterval) {
return false;
} else {
applicationScope.put(key + "_time", currentTime);
return true;
}
}
Use recycle methods
When running through a large set of Notes objects like with NotesDocumentCollection.getFirst(), getNext() watch the memory consumption of your HTTP task.
Since there are Java objects behind the JavaScript objects, then have the same requirement to call recycle() to remove them from memory.
Read Domino Designer help regarding recycle() methods of Notes Java objects.
Use firebug page speed
In Firefox you can add an extension to your firebug: page speed
.
This tool check where your website is slow and why. Very valuable.
Preload XPages engine end specific applications on startup
Starting with Notes and Domino 8.5.3, you can use the following ini parameters:
XPagesPreload=1
Preloads XPages java code at server startup so that they are already in memory when a user access an xpages app for the first time.
XPagesPreloadDB=servername!!path/mydb.nsf/myxpage.xsp,servername!!path/anotherdb.nsf
Preloads XPages engine for a specific XPage in a specific database or for all XPages in a database.
Both parameters can be used on the Domino Server and on the Notes client.
Run through a view very fast
Starting with 8.5.3, the use of a viewNavigator has been optimized:
var myview = database.getView("myview");
myview.setAutoUpdate(false);
var viewNavigator = myview.createViewNav();
viewNavigator.setBufferMaxEntries(200);
var viewEntry = viewNavigator.get();
while (viewEntry) {
// process
viewEntry = viewNavigator.getNext(viewEntry);
}
Disclaimer: this is a planned feature for 8.5.3 and it's not sure if will be in the final product.
Controlling the browser cache
You can control how the browser caches your pages by setting the http header "cache-control" like this:
var exCon = facesContext.getExternalContext();
var response = exCon.getResponse();
response.setHeader("cache-control", "somevalue");
instead of "somevalue" you can use values like this:
- no-cache: forces the browser to ignore the cache and to reload the page every time
- no-store: the browser should remove all connection data after loading
- max-age=xx: reload page if the cached page is older than xx seconds
there are more parameters, just google for "http header cache-control" to learn about them.
Multithreading
You can do things simultaneously from client side JavaScript by doing several Ajax requests.
On the server side, you can use Java. See this post from Vince Schuuman for more information about multithreading in XPages
.