The document provides tips for improving LotusScript performance by identifying and addressing bottlenecks. It discusses identifying where performance issues occur, tools for measuring performance such as using the Now function and GetThreadInfo, and avoiding common pitfalls like overuse of GetNthDocument and unnecessary code. The document emphasizes the importance of measuring performance empirically before optimizing code.
1 of 39
Downloaded 27 times
More Related Content
BP206 - Let's Give Your LotusScript a Tune-Up
1. BP 206
Let's Give Your LotusScript a Tune-Up
Craig Schumann Senior Developer, Teamstudio
Jens-B. Augustiny, CEO, LIGONET GmbH
2. Who is who?
Craig Schumann, Senior Developer at Teamstudio
Teamstudio is a producer of Development and Administration tools
for IBM Lotus Notes and Domino
Jens-B. Augustiny, CEO at LIGONET GmbH
Ligonet is a small but active Busines Partner located in Switzerland
2
3. Agenda
What do you mean it's slow?
Where do performance problems show up
Where the heck is that coming from?
Tips and tools to weed out the slow bits
Don't want to go through that again!
Tips for avoiding slowness in the first place
3
5. Bad performance... what exactly do we
mean?
The application is bad ....
Delivery time vs response time ....
Impossible to work with this application
This workflow has to be improved in any case!
Who has never heard these comments?
First and foremost - Make sure you are addressing the right problem.
5
7. Performance of WHAT?
Perceived Performance
The user is feeling that the application is not giving the expected
output
Rather difficult to define, hence rather difficult to analyze
Possible fixes:
Better user training - Explain the functionality to the
users
Enhance the experience - More information on
screen during processing or data entry
Streamline the experience - Change the process
flow
User experience can greatly influence how fast an application seems to
work. If it is frustrating or takes a long time to enter data, users may
report this as bad performance.
7
8. Real performance ....
..... or rather the lack of it ....
Bottlenecks, that can be verified by timing
Almost impossible to anticipate
Differences between testing and production environment
Any conclusion without actual timing data is pure speculation
Timing may influence the result
It is important to have empirical data before you start changing anything.
Just like with end users, developers have preconceived notions about
what the source of the problem might be
8
9. Example
Running the same functionality four times: list all the views of
names.nsf
2 parameters are changed: The loop logic and the way that we
access the DB properties
Which of the four variants is the fastest?
Why is your choice the fastest?
9
12. Conclusion
Results may surprise you
Metering should be done in a realistic environment
The amount of data and its structure has to be realistic; most testing
environments are insufficient
Approach of analysis has to be very, very systematic e.g. by
narrowing down the points of problem
12
13. Where the heck is that coming from?
So you need actual numbers to justify the work to
speed something up..... where are those supposed
to come from?
13
14. Timing with Now
Example:
BaseTime = Now
[.... your code goes here ... ]
Print Time used: & Now BaseTime
Advantages Disadvantages
Requires changing of code
Bad placement falsifies the result
Simple and cheap Insufficient timing resolution
14
15. High Resolution Timing - GetThreadInfo()
Bruce Perry once published an undocumented way to use a high
resolution timer
http://searchdomino.techtarget.com/tip/1,289483,sid4_gci895240,00.html?FromTaxonomy=%2Fpr%2F283841
stc = GetThreadInfo(LSI_THREAD_TICKS) ' get the starting tick
count
'[....the code you want To Time...]
'get the final tick count
ftc = GetThreadInfo(LSI_THREAD_TICKS)
'get the ticks per second
tps = GetThreadInfo(LSI_THREAD_TICKS_PER_SEC)
'final tick count minus starting tick count divided by ticks
per second yields duration.
t = (ftc - stc) / tps
15
16. High Resolution Timing - GetThreadInfo()
Advantages Disadvantages
Requires changing of code
Bad placement falsifies the result
Relatively Simple to implement Makes use of undocumented functions
Better resolution than using 'Now'
A bit more tricky to use
GetThreadInfo() is not guaranteed to work on all versions of Lotus
Notes
16
17. How to communicate the results
PRINT to the status bar (client) or the log.nsf (server)
Better:
Output to a document
Output to a profile document
Output into an analysis database ..... sorry ....
application
17
18. Example - Make it reusable
Class debugTimer
Private Start As Variant
Private fnName As String
Sub New( fn As String )
Set Start = Now
fnName = fn
End Sub
Sub Delete
Print fnName & " took " & Now-Start & " seconds to complete."
End Sub
End Class
18
19. Example - Make it reusable
Sub Initialize()
Dim fnTime As New debugTimer( GetThreadInfo(LSI_THREAD_PROC) )
Dim i As Integer
While i < 1000
Print i
i = i + 1
Wend
End Sub
19
20. Built in profiling
Introduced in Lotus Notes / Domino 7
速 速 速
Only for agents and Web Services
Java and LotusScript
Activation in the properties of the Agent or Service
Access to the results by right-clicking on the Agent or Service
There are only results for pure Notes-Objects, no information for
your own code
20
21. Built in profiling - Example
Sub Initialize
Dim db As New NotesDatabase( "", "names.nsf" )
i = 0
Dim s As String
For i = 0 To UBound(db.views)
s =db.Views(i).name
Print s
Next
End Sub
21
24. Teamstudio Profiler
Timing of functions
Timing of code line-by-line
Plethora of additional analysis information available
Server and Client
LotusScript only
Application is slowed down a lot
You have to pay for it
24
27. Common problems
Tooling is a must for existing applications and performance
problems, but even better would be not to create the problem to
being with!
Some of these are just rookie mistakes, others are just careless.
So first up.....
GetNthDocument!
27
28. GetNthDocument()
Running through a Doc-Collection with GetNThDocument(n) is a lot
slower than getting the first doc with GetFirstDocument and then
going through the collection by GetNextDocument (doc)
Much has been said about this ... mostly all can be read online
http://bobzblog.com/tuxedoguy.nsf/dx/getnth-revisited-helpful-function-or-spawn-of-
the-devil
http://www.lotusgeek.com/LotusGeek/LotusGeekBlog.nsf/d6plinks/ROLR-7HHPER
Be familiar with the limitations of the API you are using. There are no
bad functions, but not every function is appropriate for all situations.
28
29. Check your loop logic
found=False
Do Until (selected_doc Is Nothing)
If (selected_doc.Form(0)="fa_Term") Then
found=True
End If
Set selected_doc=term_collection.GetNextDocument(selected_doc)
Loop
Set selected_doc=term_collection.GetFirstDocument()
If Not(found=True) Then
MessageBox NO_TERM_DOCUMENTS_SELECTED_TO_DELETE, 16,
DELETE_ERROR
Exit Sub
End If
29
30. and fix your bugs....
found=False
Do Until (selected_doc Is Nothing)
If (selected_doc.Form(0)="fa_Term") Then
found=True
' loop should short circuit here!!
End If
Set selected_doc=term_collection.GetNextDocument(selected_doc)
Loop
Set selected_doc=term_collection.GetFirstDocument()
If Not(found=True) Then
MessageBox NO_TERM_DOCUMENTS_SELECTED_TO_DELETE, 16,
DELETE_ERROR
Exit Sub
End If
30
31. Fix your bugs - Code Rot
Fact - Code changes over time. Requirements change, better ways
of doing things are discovered.
Make sure your code changes are complete before moving on other
wise performance suffers
Sub Queryopen(...)
Dim session As New NotesSession
Set db = session.currentdatabase
Set view = db.getview("People")
Set ProfileDoc = db.getprofiledocument("PickerView")
' ProfileDoc.Pview = "People"
End Sub
The variable 'view' is never used anywhere on the form.
NotesDatabase.GetView() is an expensive call to make on a QueryOpen.
Especially if it is never used.
31
32. Careful with nested IFs
Unlike languages like C and Java LotusScript always evaluates all
conditions in an if statement.
x = 1
If x = 0 And checkresult( res ) = 0 Then
'do some stuff
End If
Checkresult() will always be called. Performance problems can easily be
masked in seemingly simple statements like this.
32
33. Careful with nested IFs The Fix
The correct statement is the following:
x = 1
If x = 0 Then
If checkresult( res ) Then
'do some stuff
End If
End If
Checkresult() will only be called when the first statement is true.
33
34. Variables Variant is slower
Besides being breeding grounds for bugs the
Variant data type is inherently slower than typed
variables.
LotusScript will have to figure out the type at
some point and provide a conversion to the
correct type.
Don't be lazy! Use Option Declare
34
35. Loops Some are faster than others
Forall through arrays much faster than For ..... Next
For ... Next is faster than Do ..... Loop or While ..... Wend
35
36. Left overs....
Access to selected documents is faster by accessing them through a
view instead of a document collection
Access to Notes object through a temporary variable is faster than
accessing them every time through the property of another Notes
object
36
37. Summary
There are technical and non-technical reasons for performance
issues
If the issue is technical, any statement without metering is pure
speculation
There are no two identical cases
Systematic top down analysis is very, very important
Sometimes the redesign of the application is the best way to remove
the issues
There are some best practices
37
38. Thank you!
Questions?
Maybe there are even answers ..... :-)
Craig Schumann - Teamstudio
craig_schuman@teamstudio.com
www.teamstudio.com
Jens-B. Augustiny - LIGONET GmbH
augustiny.j@ligonet.ch
www.ligonet.ch
38
39. Legal Disclaimer
息 IBM Corporation 2009. All Rights Reserved.
The information contained in this publication is provided for informational purposes only. While efforts were made to verify the completeness and accuracy of the information contained in this publication, it is provided AS IS
without warranty of any kind, express or implied. In addition, this information is based on IBMs current product plans and strategy, which are subject to change by IBM without notice. IBM shall not be responsible for any
damages arising out of the use of, or otherwise related to, this publication or any other materials. Nothing contained in this publication is intended to, nor shall have the effect of, creating any warranties or representations
from IBM or its suppliers or licensors, or altering the terms and conditions of the applicable license agreement governing the use of IBM software.
References in this presentation to IBM products, programs, or services do not imply that they will be available in all countries in which IBM operates. Product release dates and/or capabilities referenced in this presentation
may change at any time at IBMs sole discretion based on market opportunities or other factors, and are not intended to be a commitment to future product or feature availability in any way. Nothing contained in these
materials is intended to, nor shall have the effect of, stating or implying that any activities undertaken by you will result in any specific sales, revenue growth or other results.
Performance is based on measurements and projections using standard IBM benchmarks in a controlled environment. The actual throughput or performance that any user will experience will vary depending upon many
factors, including considerations such as the amount of multiprogramming in the user's job stream, the I/O configuration, the storage configuration, and the workload processed. Therefore, no assurance can be given that
an individual user will achieve results similar to those stated here.
IBM, the IBM logo, Lotus, Lotus Notes, Notes, Domino, Quickr, Sametime, WebSphere, UC2, PartnerWorld and Lotusphere are trademarks of International Business Machines Corporation in the United States, other
countries, or both. Unyte is a trademark of WebDialogs, Inc., in the United States, other countries, or both.
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.
Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or both.
Intel, Intel Centrino, Celeron, Intel Xeon, Intel SpeedStep, Itanium, and Pentium are trademarks or registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries.
UNIX is a registered trademark of The Open Group in the United States and other countries.
Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both.
Other company, product, or service names may be trademarks or service marks of others.
39
Editor's Notes
#6: Collection of user comments about bad performing applications