« On the impact of social media | Main| Struggling to figure something out »

synchronize(this);

'Nobody has ever done this before.' 'That's why it's going to work.' If you're using Domino today, chances are you're working extensively with Java code. Oh, you might not be writing Java code yourself. But you use it when you go to work, when you go to church, when you pay your taxes.... errr, sorry... when you open your Notes mail, when you go to Designer, when you access an Xpages app.

Java is all around us.  The very fabric of the Eclipse user experience is based on Java code. And whenever Java has to interact with information inside an NSF, there is but one way to do it: notes.jar.  The lotus.domino package is the standard, both inside IBM and among the Lotus community, for accessing Notes/Domino data.  It is our desert of the real.

But what if I were to tell you that this .jar is the world that has been pulled over your eyes to blind you from the truth?

You'd probably say "Nathan, you're really going overboard with this Matrix crap. Get to the point."

The truth that Notes & Domino has a backdoor -- a SECRET API that is only used by a select few.  And that it is this API that makes it possible to scale Xpages and keep Designer from processing at glacial speeds.

Click Permalink to continue...
This secret API is com.ibm.designer.domino.napi, and it is deployed in a Designer client as "com.ibm.domino.napi"  If you have Designer installed, you can find this for yourself.

If you take a closer look at this eclipse/shared/plugin, you'll make a few discoveries. Of course, the most interesting discoveries might be found using the JD-Eclipse plugin, but I would never advise that, as it is most assuredly a violation of both your license agreement, and whatever version of the DMCA might apply to your local jurisdiction. Besides, it's difficult to install it in Designer with the File - Application - Install menu select.  So stay far away from those kinds of hacker tools, okay? No good can come of it.

But even simply including the com.ibm.domino.napi plugin as a referenced library in Eclipse can provide some valuable information. It turns out that there are classes for NotesSession, NotesDatabase, NotesCollection, NotesCollectionIterator, NotesCollectionEntry, NotesNote, NotesItem and a few other less-familiar constructs.  These classes all use a more direct path to access the underlying NSF structure, as they rely on a Java Native Interface approach to make calls to the C API.  This is the same way that the Eclipse RCP itself handles standard UI components -- by providing a common Java abstraction layer to the platform-specific C libraries via SWT and Jface.  And just as in Eclipse, it is dramatically faster.

Unfortunately, the NAPI classes are more akin to the C API approach to doing things than they are to the Java approach to doing things, so lots of stuff doesn't work the way we'd really like.  Fortunately, the architecture of the Domino Java API leaves the door open for us to fix this.

You see, all the various classes of the lotus.domino package are not truly classes at all.  They are Interfaces.  In Java terms, that means that they are simply rule sets for how any actual objects should behave.  So when you say Session.getDatabase("White", "rabbit.nsf"), you're really just referring to a method which by prior contract is known to exist on whatever actual object you got for a Session.  Part of that contract is that the method will return an object that conforms to the rules of a Database.

The real objects are defined by different code. You'll find these packages in the notes.jar.  They are lotus.domino.local and lotus.domino.cso.  The lotus.domino.local package is an implementation of the lotus.domino ruleset.

So... could we make our OWN implementation of that ruleset?  Nothing about lotus.domino prevents us from doing it.  Last week, I tried it out.  Instead of using the lotus.domino.local objects to access NSF data, I imported the NAPI classes, and put a wrapper around them that implements the lotus.domino classes such as Session, Database, Document, Item, View, ViewEntryCollection and ViewEntry.  So now I can take the exact same code that I'd been running with the notes.jar, and run it with my new implementation.  As far as my higher level agent or plugin code is concerned, there is no difference.

What was the outcome?  See for yourself.



This simple Eclipse component defines 4 Jobs: two ordinary Eclipse Jobs and two NotesSessionJobs. The first two jobs access a copy of the events4.nsf, in which I have copy & pasted every event message, so there's just shy of 15,000 documents in that database. The second two jobs access an exact copy of that first NSF.  I point them at a different file simply to avoid any file lock conflicts between the two implementations.

For each job, the task is simple: open up a View, start at the beginning, and read out a piece of information from each row in the view, then proceed to the next row.  Each implementation has two versions of the process, one that gets the information via a ViewEntry.getColumnValues and another that gets the Document and does a .getFirstItem().getText().  Here's a snippet directly from the source code...

ViewEntryCollection localColl = localView.getAllEntries();
ViewEntry curEntry = localColl.getFirstEntry();
ViewEntry nextEntry;
String whatever;
while (curEntry != null) {
        nextEntry = localColl.getNextEntry(curEntry);
        whatever = curEntry.getColumnValues().elementAt(4).toString();
        curEntry.recycle();
        curEntry = nextEntry;
}

The developers among us have all seen this pattern about a billion times. But even the end-users (oh, and administrators) among us run code that does this, because it's part of how your email and calendar applications display their information.  So you can imagine what kind of impact it would have on all aspects of the modern Notes/Domino experience if NSF data could be access 3 to 6 times faster than it is today!  Tragically, the NAPI implementation is only about 0.1% of the overall API, so it's only useful for a few specialized tasks.  For instance, right now, it can only read information from an NSF, not write it.

When I stumbled upon the NAPI package, I asked IBM about it.  "This looks really cool, but it's only a tiny part of the API. When are you going to finish it?"  The reply was basically "we'd like to finish it because it's much faster, but there's no customer demand for it."

No customer demand!?  To make the API that underpins every aspect of the Notes 8 messaging UI, Designer in Eclipse, and every single aspect of every single Xpages application FOUR TIMES FASTER!??!?!?

Do you, dear reader, demand to make the single most important piece of Notes/Domino 8+ way, way better?  I certainly do.  And if we want to convince them of it, we will need to file PMRs, call sales reps, email product managers, buy developers a beer, blog, tweet, and stick your head out your window and yell "THIS API IS SLOW AS HELL, AND I'M NOT GONNA TAKE IT ANYMORE!!"

Incidentally, while I was at it, I made my implementation do away with .recycle().  Well, technically it doesn't do away with it, so much as make it totally irrelevant to the average user of the API. How? By making all the underlying objects recycle-proof.  Just like the current API, the underlying code still performs a recycle to release the C memory handle.  But even when it does, it retains enough information about where it got that handle in the first place to re-establish it as needed.  So you never get a "object has been recycled" error.  Because of this, we can aggressively recycle automatically behind the scenes.  So, for instance, when you are looping through an EntryCollection, a call to .getNextEntry() will automatically recycle the previous entry, since you probably don't need it anymore.  But if it turns out that we guessed wrong, and you DO need it, no problem.  It's totally invisible to you when we re-establish the binding.

I'm sure someone is wondering when they'll be able to download this from OpenNTF.  I'm looking into it.  But one thing that would certainly help would be if all of your very loudly and very publically insisted that IBM get to work on making the NAPI package complete and fully supported.  If they'd commit to implementing a few key features at the JNI layer, I will try to get the executives at GROUP to allow me to open source our implementation layer, and we can all pile on and do the grunt work of implementing every little nuance convenience method defined by the lotus.domino Interfaces.

Have a great weekend!

Comments

1 - Very juicy indeed. Of course, implementing your own interface for some classes is an old trick, one that Bob Balaban has been advocating for something as simple as debugging an AgentContext outside of designer for years. Shouldn't this be an IdeaJam idea?

2 - That is astonishing

As part of a small Notes development team fighting against a new IT Director (a self proclaimed Notes hater), this is the sort of help from IBM we need to stay using Notes/in a job!

Tell me which window to stick my head out of and I'll fill up on throat sweets and scream until my larynx dissolves!

3 - Interesting comparison. Had not expected it to be such a difference in performance.
I guess that com.ibm.designer.domino.napi is unsupported and internal IBM code, but there's nobody stopping you from writing your own Eclipse plugin that bundles native libraries (dll's for Windows, .so for Linux, .jnilib for Mac) that calls C API functions, together with a Java API that calls them using the JNI framework (Java Native Interface).
Just search the web for "Bundle-NativeCode" to see how to define them. And the cool thing is that XPages with support those Eclipse plugins with bundled native libs in 8.5.2 (based on announces at Lotusphere 2010). There will even be support for the Eclipse plugin system (OSGi) on the Domino server.

4 - Wow, Nathan, that is dramatic. I like the recycle thing, I know we all will.

@mike - been there several times with the notes haters. I feel for ya.

5 - Need(this)

6 - Jake, yes many of us have wrapped the Notes Java API to hide recycle and get sane modern "user" APIs, but what we've been wrapping is Notes.jar. Nothing new there. This is different. Talking directly to the c API without going through the C++ layer like Notes.jar and Lotusscript do also opens up the entire API to Java.

While I appreciate the performance gains, I'm personally more interested in having access to more of the c API via JNI and building APIs on top of that.

Didn't Bill Buchan build something like a c API to LS "translator" to generate LS stubs for c API calls? Maybe something similar could be done for JNI.

7 - ok, I'm doing my part: { Link }

btw, if you're scared like me of messing with eclipse plugins, JD-GUI may be an alternative to JD-Eclipse plugin

8 - Wow! Thanks for this post, very interesting info. Amazing differences in speed, I can’t believe something like this with potential of fixing so many weaknesses isn’t a top priority?

Fredrik

9 - @1 - Oh there's an awful lot you can do by building your own Implementation for sure. There's no reason at all why your data layer HAS to be an NSF. Actually the CORBA stuff doesn't even know what storage layer is, does it?

@2 - Thanks Mike. One part of it that really gets me is that the difference in ViewEntry iteration is key to the myth that Domino doesn't scale. In fact, my understanding is that Xpages tries to use napi for rendering Domino Views, but I could be mistaken about this.

@3 - The performance difference is emphasized by the fact that everything in lotus.domino.local is synchronized to the entire object. But I can't tell you how I know this. Emoticon

And yes, building your own JNI is definitely possible. But I wouldn't want to have to support it. If I were going to bother with that, why even go to NSF? Pick a storage medium that has a native Java API and be done with it.

@5 - rofl

@6 - JNI code generators abound. Two immediate hits from Google: { Link } { Link }

@8 - The only thing I can figure is that since a better Java API doesn't make Domino a better messaging server or lower TCO, none of IBM's enterprise customers care about it. Emoticon

10 - I wonder... Are you getting around ECLs with this approach?

The reason I ask is that I recall Gary Devendorf once telling me that the back-end classes would be much, much faster if they didn't have lots of ECL checks built into them for when they run in front-end code. A good reason why IBM would have a "secret" set of classes could be that they are doing an end-run around the ECLs.

But then again, you're talking about Java, so you're not talking about code that runs in the front-end...

-rich

11 - @10 - It does bypass ECLs. And what do you mean "not talking about code that runs in the front-end"? Did you click on the image to watch the video link? My demo is a Notes plugin. Then again, the entire plugin context isn't really subject to ECLs. It's only subject to the java.policy set by the security manager.

If ECLs are causing a runtime of 3 to 6 times greater than without, then dear god we need a way to turn them OFF! 99 out of 100 Notes shops just tell their users to click "trust signer" on the dialog anyway. And they don't even exist on server-based processes!

But honestly, I don't think you can attribute a 6000ms vs 1000ms runtime to just ECL checks.

12 - No, I didn't click through. I trusted what you wrote and didn't need to see the demo. I meant the 'traditioinal' front-end. I'm aware that the plugin environment and back-end agent don't honor ECLs, but since they're going through the same jar and the same DLL I presume some of the overhead is still there even if it is ignored. I recall it being hard to believe when Gary Dev told me that the COM classes were way faster than the LotusScript classes due to the fact that they bypass the ECL-checking layer. This was a very long time ago, of course and Gary may or may not have been oversimplifying. Your post just rang that bell for me, that's all.

13 - "No customer demand." What?!???! Do I have to open a PMR for each point release of Domino that comes out saying "Hi, I'd like to open an enhancement request SPR for MAKING EVERYTHING FASTER KTHXBYE"??

*Sigh.* I don't whether to feel exasperated or resigned.

Oh wait, perhaps I've figured it out... more speed might cut into per-processor server license sales. And that would be bad, right?

You should definitely check this against a server.

14 - @12 - The COM classes run against the same LSX broker that Lotusscript and the lotus.domino.local Java API do. I don't know why Gary would have said that about COM. (Well, other than the fact that he works for Microsoft.) That's why the existing Java API is exactly as fast in most operations as Lotusscript. You don't get any language benefit whatsoever, even though Java's threading support is far more robust.

@13 - Yeah, like I said... the support process is the Achilles' heel for Lotus right now. Basing all your product decisions on PMR demand is great if you're a middleware company, but it fails completely in the realm of business solutions, where end-user experience rules the day. The end-user doesn't open a PMR. He just switches to a different solution and never tells you until it's time to pay maintenance.

And yeah, I'll run it on a server. I just have to set up an 8.5.2 server first, because the security manager prevents the napi package from being called from Xpages. It has to be deployed as an OSGi plugin first, and that means the new server build. (I only know this because a very senior developer told me so.)

That being said, I expect that the issue will be even more emphasized in a server context because of the synchronization issue. You simply can't do real multi-threading on the same NSF in the existing API. Every call pushes to the same thread, which has the same Session object, which serves up the same Database objects, all of which have every method synchronized to the entire object. Hence the title of this post.

It's a Java 1.1 API that's hasn't had a close look in about a decade, and in the meantime, the entire platform has become achingly dependent on it.

By the way, I literally laughed out loud at your PMR proposal.

15 - When you profile some Notes code in Eclipse using TPTP you can see how the standard Notes API uses the NAPI stuff :)

16 - @Nathan, 7 etc

Glad to see the 'decompiling a jar file' cat is out of the bag.

If you have lots and lots of jars that need decompiling this will help:

{ Link }

Keith

17 - @14 - Just to clarify, Gary was still at Lotus when that conversation occurred. I was skeptical at the time for the very reasons you stated.

18 - This is AWESOME stuff Nathan (and thanks for sharing). I get the impression I have been wasting my time these past few years posting all my ideas for expanding the Notes product on IdeaJam. Perhaps I should have been sending them directly to you for action! I am trying to imagine what the impact might be if IBM were to find a way to share the many secrets hidden away inside the new Eclipse framework with the development community. Perhaps that would give those of use missing those extra 50 IQ points the chance to push the boundaries of our own notes applications. It seems like we are only touching the surface of the full potential of Notes development. Yes we all look forward to the new features being added with the next great release. But do we truly understand the power of what we already have? Every one of your (and Tim's) recent posts makes me feel like I know and understand less and less about what we have.
ps: Will this new find allow us to do a JOIN?

19 - @18 - Working on this, one of my first thoughts was to use the accelerated Entry handling to improve my Tigerstyle demo. Alas, there are enough gaps in the JNI side of things to prevent this. Chiefly, there is no rendition of NIFFindByKey, and there IDTable implementation is far too incomplete. (How do you not include IDInsert, IBM?)

No one person can really know the power of what we have today. It's far too much. Do you know how many Java packages are available in Xpages on a Domino 8.5.1 server? About 1500. The core Harmony runtime alone has 900 packages! (And yes, dear readers, I actually counted.) It's way, way too big for anyone to digest any more. It will never be entirely documented.

20 -
Interesting find, Nathan.

I think if I were making a product that does a whole lot of the same thing sequentially -- like searching a bunch of databases or something -- I would find this pretty interesting.



21 - @20 - roflmao!

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Search 

Disclaimer 

Welcome to Escape Velocity!

Opinions expressed here by Nathan T. Freeman are not necessarily those of his employer. However, there's a decent chance they are, so check with them if you really want to know.

But really... do you need that kind of validation? Are the opinions expressed here in doubt?

MiscLinks