Domino Connection


Performance sample

This sample application models a fairly typical situation. Given a text file (i.e. from a host system) containing customer data, it imports the file into Domino by creating documents. After that, in a second step, it finds out about some special customer properties like the most valuable customer within a certain area.

Assume the text file contains the following, tab separated entries per line:

If you want to run the sample code, you will have to create the text file and the Domino database.

The Domino databases features a single form called "CustomerData" and a single view called "By Customer Name" providing the following columns: Name, Zip, Sales.

Slow Solution

Here is the slow solution of the ASCII file import.

| inFile db note values |
"Startup runtime system"
AbtLnEnvironment startUp.
 
"Open the import database"
db := AbtLnConnection local openDatabase: 'vasample\perf.nsf'.
 
"Open the text file"
inFile := CfsReadFileStream open: 'c:\notes\data\vasample\test.txt'.
 
"Read lines till the end of the file"
[inFile atEnd] whileFalse: [
"Convert line into a collection, words are tab (9) separated"
values := inFile nextLine subStrings: (9 asCharacter).
 
"Create a new document from the form definition"
"Execute the default value formulas"
"This is time consuming !!"
note := db newNoteFromComputedForm: 'CustomerData'.
 
"Set values"
note at: 'Name' put: (values at: 1).
note at: 'Zip' put: (values at: 2).
note at: 'Sales' put: ((values at: 3) asNumber ).
 
"store the document"
note store.
].
 
"Close the database and the file"
db close.
inFile close.
 
"Shutdown runtime system"
AbtLnEnvironment shutDown.

After importing the data comes the second part of the job: Find the best sales for a certain region (defined by the first digit of the zip code).

| inFile db  highScore zipRegion zipScore currentScore time |
 
"Start runtime system"
AbtLnEnvironment startUp.
 
"Open the database"
db := AbtLnConnection local openDatabase: 'vasample\perf.nsf'.
 
"Initialize the highscore dictionary"
highScore := Dictionary new.
 
"Read every note"
"This is time consuming because you actually have to open
every note in the database"
db allNotes do: [ :note |
note fill.
"Find the zip region and compare the sales"
zipRegion := ((note at: 'Zip' ) at: 1).
currentScore := (note at: 'Sales').
zipScore := highScore at: zipRegion
ifAbsent: [ highScore at: zipRegion put: currentScore.].
(zipScore <= currentScore)
ifTrue: [ highScore at: zipRegion put: currentScore ]
].
db close.
AbtLnEnvironment shutDown.

Fast Solution

Taking into account the guideline of Performance considerations, the previous code for file conversion into documents should look like this:

| inFile db note values |
"Startup runtime system"
AbtLnEnvironment startUp.
 
"Open the import database"
db := AbtLnConnection local openDatabase: 'vasample\perf.nsf'.
 
"Open the text file"
inFile := CfsReadFileStream open: 'c:\notes\data\vasample\test.txt'.
 
"Read lines till the end of the file"
[inFile atEnd] whileFalse: [
"Convert line into a collection, words are tab (9) separated"
values := inFile nextLine subStrings: (9 asCharacter).
 
"Create a new empty note without items"
"This is a smart solution, because you know
every item you want to include and you are
not interested in default values"
note := db newNote.
 
"Add appropriate items and values step by step"
note addTextNamed: 'Name'.
note at: 'Name' put: (values at: 1).
note addTextNamed: 'Zip'.
note at: 'Zip' put: (values at: 2).
note addNumberNamed: 'Sales'.
note at: 'Sales' put: ((values at: 3) asNumber ).
 
"store the document"
note store.
].
 
"Close the database"
db close.
 
"Shutdown runtime system"
AbtLnEnvironment shutDown.

This implementation is about twice as fast as the code presented in Slow Solution. The main difference is the use of newNote instead of newNoteFromComputedForm:. The latter retrieves the form note from the database each time it is called and in addition to that executes all form formulas. As you just want to pass values into documents this is unnecessary.

The following code shows how to optimize the second job - finding the best sales for a zip code region. First you have to create a second view in the database. It should be called "Sales by ZipCode" and should have the following structure: The first column holds the first number of the Zip code of every document and must be categorized. The second column holds the sales figures sorted in descending order. Now you can use an AbtLnDatabaseView to retrieve the data already preprocessed for you.

| inFile db  highScore zipRegion zipScore currentScore time view|
"Start runtime system"
AbtLnEnvironment startUp.
 
"Open the database"
db := AbtLnConnection local openDatabase: 'vasample\perf.nsf'.
 
"Initialize the highscore dictionary"
highScore := Dictionary new.
 
"Open the view"
view := db openViewRebuild: 'Sales by ZipCode'.
 
"Get the all categories from the root node"
view root children do: [ :node |
"As the second column is sorted, select the
first entry of the collection returned by expanding the
category nodes. Do not open the note but retrieve the values
from the pseudo note contained in the document node"
highScore at: (node category)
put: (node children first pseudoNote at: 'Sales').
].
 
"Close the database"
db close.
 
"Shutdown runtime system"
AbtLnEnvironment shutDown.

Depending on the size of the database this implementation is two to four times faster than the solution presented in Slow Solution. The main advantage is that you use the Domino indexing facility to preprocess the data. Using special views is a good practice to speed up search and indexing operations for your Domino Connection applications.


[ Top of Page | Previous Page | Next Page | Table of Contents ]