Wednesday 8 June 2011

Memory Management in XPages

So, I am sitting on the coach to the 2011 Lotusphere party at the new Harry Potter World. Who should be sitting in the seat behind me, but the estimable Jeremy Hodge. We chatted, as you do, about memory management in XPages.
Several years ago, a major customer was having problems as a result of a significant Notes application that was crashing their production application servers. They had outsourced the development of this mission critical application to an organisation who had used contract Notes developers to write Java agents. These developers hadn't had this chat with Jeremy !
As a LotusScript developer, you would naturally want to convert your existing code to process through the documents in a view, to server-side Javascript as follows:
var aView:NotesView = database.getView("SomeViewName");
var doc:NotesDocument = aView.getFirstDocument();
while (doc)  {
// do some processing on doc
doc = aView.getNextDocument( doc );
}
However, this code could cause the problem that my customer was experiencing, if there were a large number of documents in the view.
In XPages, the above code needs to be written like this:

var aView:NotesView = database.getView("SomeViewName");
var doc:NotesDocument = aView.getFirstDocument();                               // line 1
while (doc)  {
// do some processing on doc
var nextdoc:NotesDocument = aView.getNextDocument( doc );  // line 2
doc.recycle();                                                                                          // line 3
var doc:NotesDocument = nextdoc;                                                   // line 4
}
Jeremy explained to me that in the first case a Notes document object is instantiated in memory for each document in the view. 'doc' is only a pointer to the last object created. In the case where there are many documents in the view, the memory on the Domino server eventually fills up, the servers slows and eventually can crash. Bad, bad, bad !
At 'line 1' above, the first Notes document object gets instantiated in memory, with doc created as a pointer to that memory location. At line 2 a second Notes document object gets instantiated in memory, with nextdoc created as a pointer to that memory location. Line 3 sets the first document object for garbage collection. Line 4 creates a new doc pointer and sets it's value to the memory location pointed to by nextdoc. The two pointers, doc and nextdoc now both point to the only Notes document object being retained in memory.
As we go round the while loop, processing through the view, a new Notes document object gets instantiated, with nextdoc set to it's memory location; the object pointed to by doc gets set for garbage collection and doc is then set to point to the same memory location as nextdoc. Voila ! Only ever a maximum of two Notes document objects, with all their methods and properties, taking up memory.
If you want to be really good, you could add this statement after the while loop:
aView.recycle();
When using objects in an agent, all objects are destroyed when the agent ends. When using servlets, .jsp's, or standalone applications, recycle must be used since Domino will never clean up these backend objects.

Warning: never recycle an object that you have open in the UI. This will generate the error "object has been recycled or removed" and you will have to use 'trial and error' to determine which one you inadvertently recycled !
There are just so many benefits from attending Lotusphere. Some that you can't even anticipate !

1 comment:

  1. Hi,

    Thanks for a nice post, may I have one question
    why do we need to redeclare the doc variable in line 4, is this possible to use like this:

    doc.recycle()
    doc = nextDoc

    Thanks!

    ReplyDelete