XPages

On synchronization in XPages

The biggest issue that we had with XPages in 8.5.0 was performance, every piece of code you wrote had to be optimised to get the best performance, something which us Notes developers have spent all too little time on in the past.

With 8.5.1 everything is faster from DDE onwards, but there are some code changes that we can take advantage of to make things even better. Most important of these is synchronization. For those of you who know Java this will be a familiar concept that has just been implemented into Server Side JavaScript (SSJS). But for the LotusScript developer, here is my quick attempt at explaining it...

If you have a commonly used piece of code, it will be called by multiple different areas of the system at the same time (or at least very close together) and return the same result. If you're doing some expensive piece of work (such as a DbLookup) then all of the calls to that code will run and there will be an inevitable performance hit.

By adding the synchronize wrapper around the "expensive" code what will happen is that all of the calls to that code will queue up behind each other, so that code can only run once at a time. We can then cache the results of the code so that all of the queued up calls can just get that result from memory (the applicationScope for example) rather than having to go off and calculate it again and again. A very simple concept but one which saves a huge amount of processing time.

But what will our code look like? Well here is a sample function from the upcoming IQJam application that will be launching later this week.

function getControlPanelFieldString(fieldname){

synchronized(applicationScope){

if(isCacheInvalid("controlpanel_" + fieldname, 600)){

var controlPanels = database.getView("lookupControlPanel");

var controlPanel = controlPanels.getFirstDocument();

applicationScope.put("controlpanel_" + fieldname, controlPanel.getItemValueString(fieldname));

controlPanel = null;

controlPanels = null;

}

  return applicationScope.get("controlpanel_" + fieldname);

}

/**

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;

}

}

We store lots of tiny variables about the application in a "Control Panel" document and then read them as needed into the applicationScope. The nature of the variables is that they don't change much so we can cache them for long periods of time (10 minutes in this case).

As with lots of XPages code, the idea for this came from the Discussion template (which is quite dramatically different under the covers in 8.5.1), so I'd highly recommend digging through the code in there to get an idea of what you can do with XPages. And of course we have to offer thanks to Thomas Gumz and the other XPages developers in IBM who write the code that the rest of us can then re-use for our own dastardly ends.

Disclaimer: Notes/Domino 8.5.1 is beta software and no features are guaranteed until release.