DOTS (Domino OSGi Tasklet Service) project has been contributed into OpenNTF last year. Basically, it provides a way to create server tasks for Java developers.

This is huge. Basically we could run our Java code in a similar way with a couple of other techniques, but DOTS provide many advantages. I'll dive deep on this in a seperate blog post. For now, take it as a teaser :)

You can refer to Niklas's blog entry to setup DOTS in your environment.

For this experiment, I'm using an exploded version of FakeNames database by David Leedy. In the past, I have duplicated all contents for several times and I'm still using it to crash my server :)

Image:Experimenting DOTS task vs. Java Agent

First, I have created a 'terrible' Java agent which does nothing.

import java.util.Date; 

import lotus.domino.AgentBase;
import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;

public class JavaAgent extends AgentBase {

       public void NotesMain() {

               try {
                       Session session = getSession();
                       AgentContext agentContext = session.getAgentContext();

                       Date startTime=new Date();

                       Database db=getSession().getDatabase("", "test/fakenames.nsf", false);

                       longJob(db);

                       long duration=((new Date().getTime()) - startTime.getTime())/1000;                
                       System.out.println("Finished in " + String.valueOf(duration) + " secs... - ");

               } catch(Exception e) {
                       e.printStackTrace();
               }
       }


       public void longJob(Database db) throws NotesException {

               int count=0;

               View view=db.getView("byName");

               System.out.println(view.getTopLevelEntryCount());

               for(int i=0; i < view.getTopLevelEntryCount(); i++) {
                       Document doc=view.getNthDocument(i);

                       if(doc!=null) {
                               if(doc.getItemValueString("FirstName").startsWith("Sa")) {
                                       count++;
                               }

                               doc.recycle();
                       }
               }

               view.recycle();

               System.out.println(count);
       }

}


As I said before, it does nothing but counting people that has a first name starts with "Sa". So it does something, consume memory and CPU. Who cares :)

Then I implemented the same code as a DOTS task:

import java.util.Date; 

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.View;

import org.eclipse.core.runtime.IProgressMonitor;

import com.ibm.dots.annotation.RunOnStart;
import com.ibm.dots.task.AbstractServerTaskExt;
import com.ibm.dots.task.RunWhen;

public class AnnotatedTasklet extends AbstractServerTaskExt {

       public AnnotatedTasklet() {
       }

       public void dispose() throws NotesException {
       }

       @Override
       protected void doRun(RunWhen runWhen, IProgressMonitor monitor)        throws NotesException {
       }
       
       @RunOnStart
       public void runOnStart( IProgressMonitor monitor ) throws NotesException {
               Date startTime=new Date();

               Database db=getSession().getDatabase("", "test/fakenames.nsf", false);
               
               longJob(db);
               
               long duration=((new Date().getTime()) - startTime.getTime())/1000;                
               logMessage("Finished in " + String.valueOf(duration) + " secs...");
       }
       
       public void longJob(Database db) throws NotesException {
               
               int count=0;
               
               View view=db.getView("byName");

               System.out.println(view.getTopLevelEntryCount());
               
               for(int i=0; i < view.getTopLevelEntryCount(); i++) {
                       Document doc=view.getNthDocument(i);
               
                       if(doc!=null) {
                               if(doc.getItemValueString("FirstName").startsWith("Sa")) {
                                       count++;
                               }
                               
                               doc.recycle();
                       }
               }
               
               view.recycle();
               
               System.out.println(count);
       }
}


Now, results:

> tell amgr run "test\XPagescrash.nsf" 'LongJobAgent' 
09.11.2012 19:38:39   JVM: Java Virtual Machine initialized.
09.11.2012 19:38:39   AMgr: Start executing agent 'LongJobAgent' in 'test\XPagescrash.nsf'
09.11.2012 19:38:39   Agent Manager: Agent printing: 181349
09.11.2012 19:41:02   Agent Manager: Agent printing: 2227
09.11.2012 19:41:02   Agent Manager: Agent printing: Finished in 143 secs... -
09.11.2012 19:41:02   AMgr: Agent 'LongJobAgent' in 'test\XPagescrash.nsf' completed execution


> load dots 
> Listening for transport dt_socket at address: 8001
> WARNING: Using pde configuration New_configuration located in C:\Lotus\Domino\Data\domino\workspace-dots\pde.launch.ini
09.11.2012 19:42:40   Domino OSGi Tasklet Container started ( profile DOTS )
> 181349
> 2227
09.11.2012 19:43:22   [DOTS] (annotated) Finished in 41 secs...


You got the idea. The same Java routine runs in 143 seconds as a Java agent and 41 seconds as a DOTS task*.


(*) Clinical trials from Developi labs :)
Serdar Basegmez   |   November 9 2012 08:45:00 PM   |    Development  XPages  DOTS  OSGi    |  
  |   Next   |   Previous

Comments (4)

Gravatar Image
Serdar Basegmez    http://lotusnotus.com    11/15/2012 2:01:44 AM

@Fero, in fact, getNthDocument() is a really fast method. Since the database is not modified, I don't think autoupdate will effect.

However, in a normal database, if you are using view.getNthDocument(), autoupdate should be false to prevent bad things :)

Of course, I suggest view navigator :)

Gravatar Image
Serdar Basegmez    http://lotusnotus.com    11/15/2012 1:59:28 AM

@Tommy, Interestingly, Amgr consumes more CPU and less memory.

We have discussed this. Nathan commented about the JVM and I think that could be the source of this difference.

DOTS is running on a persistent JVM. However, each Java agent call causes a JVM instance and it prepares all objects, NRPC connections from the scratch. We have calculated the runtime only. Looking to the start-up times, we can see amgr has an additional overhead there.

Gravatar Image
Fero Kossuth       11/14/2012 12:12:45 AM

It could be much faster without getNthDocument() and with autoupdate set to false, I assume :-)

Verry interresting find, tho, thanks.

Gravatar Image
Tommy Valand    http://dontpanic82.blogspot.com    11/09/2012 10:07:24 PM

Do you know why there's such big difference? Did you check the cpu usage on the server when running the two tasks?

Could it be some kind of CPU quota that limits the agent?