Mika Heinonen's Blog
Counter
2810

LotusScript Speed Testing
Monday, 15 August 2005 19:22:01 EET

The goal of this project is to document which methods doing the same job in a specific application need in LotusScript are the fastest.
The test database can be downloaded from here: http://siipi.com/public/mika.nsf/pages/files/$file/getcolumnvalues.nsf
The database has no documents, so you need to run the agent "Create 10000 Products" before you can run the test agents.
It would be interesting to gather timings also from other people, so if you want to try one of the agents ("GetColumnValue vs DirectField", "TraverseView") on your Notes, please post your results here.

First test results:

1) @GetDocField() is faster than @DbLookup()



2) NotesDocument.GetItemValue("FieldName")(0) is faster than NotesDocument.FieldName(0), and surprisingly both are way faster than NotesDocument.ColumnValues(ColumnNumber).

NotesView.GetEntryByKey() is slightly faster than NotesDocument.ColumnValues(), but still much slower than the first two methods.

Typical times for the 4 loops (in seconds), the first column was a test run with McAfee On-Access scan enabled, so it was a bit slower for all Methods, the 2nd colum is a typical test run which didn't change much after multiple repeated runs:
Method 1) 18.42, 14.23 (NotesView.GetDocumentByKey()+NotesDocument.FieldName())
Method 2) 14.06, 12.87 (NotesView.GetDocumentByKey()+NotesDocument.GetItemValue())
Method 3) 25.74, 18.13 (NotesView.GetDocumentByKey()+NotesDocument.ColumnValues())
Method 4) 21.29, 17.73 (NotesView.GetEntryByKey()+NotesViewEntry.ColumnValues())
This test was done with a R7 Beta 4 Client where the database was on Local.

Here are test results when the agent was ran by the server itself, via HTTP or the Agent Manager,
and below when it was run from a Notes Client while the database was on a server:

On ServerHTTPHTTPAmgrAmgr
doc.FieldName
25.25
31.63
26.70
24.81
doc.GetItemValue
20.53
22.05
21.62
20.36
doc.GetColumnValues
30.47
29.58
26.06
23.70
view.GetEntryByKey
24.23
25.42
23.55
22.35
On ClientDb on Server
doc.FieldName
137.93
136.23
doc.GetItemValue
133.25
131.18
doc.GetColumnValues
137.31
134.33
view.GetEntryByKey
117.38
115.33

Note that view.GetEntryByKey is the fastest method only when the agent is ran from a Client and the database is on a Server.
In all other cases the doc.GetItemValue is the fastest method.

This test was only to find out what is the fastest method to get a single document's fields by key from a view or database.
If the document UNID is available in the application, I would assume that NotesDatabase.GetDocumentByUNID would add some more speed.



3) Next I have to test also what is the fastest traversing speed if you want to scan the fields of multiple documents, the competitors are:
1) NotesView.GetNextDocument
2) NotesView.GetNthDocument
3) NotesViewNavigator.GetFirstEntry
4) NotesViewNavigator.GetNthEntry
5) NotesViewEntryCollection.GetNext
6) NotesViewEntryCollection.GetNextDocument
7) NotesViewEntryCollection.GetNth
8) NotesViewEntryCollection.GotoPos
8) NotesViewEntryCollection.GotoNext
10) NotesViewEntryCollection.GotoNextDocument
NotesDocumentCollection is disqualified from this race since it doesn't return the documents in the view order.


Check out also the discussion on LDD6: LDD Post


Villi
Wednesday, 17 August 2005 19:12:20 EET
I have a hard time beliving that doc.ColumnValues(1) is faster than doc.getitemvalue("itemname")(0). Could it be a R7 thing? Did you iterate through a few docs (although I dont see how that makes a difference). With doc.getitemvalue, you need a handle to the doc, and a handle to the item, to get the value. With columnvalues all you need is a handle to the view (actually a document in a view). I have never measured, so I have to take your word for it, and change my programming habits (I like getitemvalue better anyway).

As for the getnextdoc(doc) and getnthdoc(i%) - dont even bother testing - getnth always starts from the top, so if you have more than 10-20 docs, then getnextdoc is way faster.

vh

p.s.
thanks for doing these tests. i seem to remember a red book, or a white paper on LS performance a while back. you should offer IBM your services and update that book/paper:)



Mika Heinonen
Wednesday, 17 August 2005 20:56:12 EET
Villi said: "I have a hard time beliving that doc.ColumnValues(1) is faster than doc.getitemvalue("itemname")(0)."

You probable meant it the other way around?
Like: "I have a hard time beliving that doc.ColumnValues(1) is slower than doc.getitemvalue("itemname")(0).

Indeed, from the current test results, view.GetNextDocument+doc.GetItemValue("FieldName")(0) is the fastest view traversing AND single document lookup method. The only case where it is not the fastest, is when the Notes Client operates on a remote database, which should not be done anyway. Rather make an web application, make a local replica and use Notes' scheduled replicator to replicate it every 1 min or so, or use agent.RunOnServer.

I had also hard time believing that doc.GetItemValue("FieldName")(0) is faster than doc.FieldName(0). Now I have to rewrite all my applications, but the good thing is that GetItemValue(..) is more dynamic anyway, so you don't have to hardcode field names in your application.

Villi
Friday, 19 August 2005 15:31:34 EET
Sorry, got it mixed up (too much beer).

Your measurements are very interesting, but you do this on R7 beta, so the jury is still out.

.columnvalues() is just as "hard coded" as .getitemvalues(). With getitemvalues() you define constants i.e. fieldCustomer = "Customer" and refer to the constant, with .columnvalues() you tend to use magig numbers i.e. .columvalues(1) (I do anyway), and that fails if the view changes.


Stan Rogers
Saturday, 20 August 2005 08:01:18 EET
Create an integer list of columns using the index in view.Columns as the data and the column programmatic name (which will be a fieldname or, at worst, a meaningful label if you've created the view correctly) as the list tag. It's a bit of overhead for a single instance, but if you want to extract a subset of the data in a view traversal, using a meaningful name rather than a numerical index will prevent a lot of potential problems. A view's columns may be re-ordered without requiring a complete restructuring of the database, so it is possible that someone might unknowingly modify a view without investiv=gating allof the code that might touch it. It is highly unlikely that a field name would be changed so cavalierly, even by the most incompetent developer. (Think of the column programmatic name in terms of a variable name rather than as a constant per se, since a field is semiotically much more closely related to a persisted variable than it is to a simple string constant associated to a value.)

sport television
Friday, 30 June 2006 17:24:32 EET
I don't understand :( but,I think Your site is great, and i see lot off great infos here.

Best regards from Mike

<a href="http://frunny-video.blogspot.com/2006/06/pamela-rogers-video.html"><b>Clip - Rogers Pamela</b></a>

Dex
Saturday, 02 September 2006 01:05:15 EET
Using .GetItemValue is faster because of the order that it evaluates the language. Document.xxxx could be looking for a property, method, or field. They are checked in that order, properties first, then methods, then fields. .GetItemValue gets resolved faster because it only has to check the properties and some of the methods for a match, where .fieldname has to check all the properties, all the methods, and some of the fields for a match.