API
@-Formulas
JavaScript
LotusScript
Reg Exp
Web Design
Notes Client
XPages
 
Timing LotusScript Agents
Last week I published a tip talking about how simply making sure your variables have the correct data type can speed up your application. I realized when publishing that tip that there isn't anything on the Breaking Par web site that talks about how to time an agent. (Well, there is the LS2J method, but this is a lot easier). It's really quite simple, and I thought I'd mention it with this tip.

The key to timing any LotusScript is the GetThreadInfo function. This is a documented, built-in LotusScript function. (Compared to Lsi_info, which is not documented). There are many things you can do with the function. In the debugging practices tip, GetThreadInfo(1) is used to get the name of the current function or subroutine.

For timing, there is GetThreadInfo(6) which tells you the "number of ticks" and GetThreadInfo(7) which tells you how many ticks are in a second. There are also built-in LotusScript constants LSI_THREAD_TICKS and LSI_THREAD_TICKS_PER_SEC if you want to use those instead of the numbers 6 and 7.

You should define a couple of variables at the start of your agent or LotusScript code you want to time:

Dim startTic As Long
Dim seconds As Double

Next, at the start of the code, capture the current number of ticks:

startTic = Getthreadinfo(6)

Then run through the code you want to time. At the end, compute the number of seconds that the code took:

seconds = (Getthreadinfo(6) - startTic) / Getthreadinfo(7)

I like to print out the timing to the user's status bar - it doesn't really interrupt their work and they can see the time it took. For some applications that have been around a while, I've had long time users come back and say "I downloaded the new version of Notes and things are faster - the task that used to run in 4 1/2 seconds now runs in less than 3" or something similar. Here's code I use to print the message to the status bar:

Print "Finished. The code ran for " & Format$(seconds, "##0.00") & " seconds."

I format the number of seconds to two decimal places. I only allow for 3 digits - if code is running for longer than 16.65 minutes (999 seconds), then it's not something a user is going to be doing with their client (I'll either write it as a client background agent or I won't want the user to know that it actually took 17 minutes or longer to run).

One exception would be running an agent through "tell amgr run". These agents run on the server and don't show up under "show tasks". You might want to see the progress of these agents. For those agents, I print out a status every 30 seconds just to let everyone know it's still running. I do that with something similar to this:

Dim startTic As Long
Dim seconds As Double
Dim lastPrintSeconds As Double
Dim minutes As Double
Dim session As New NotesSession
Dim currDb As NotesDatabase
Dim agentName As String

Set currDb = session.CurrentDatabase
agentName = session.CurrentAgent.Name
startTic = Getthreadinfo(6)
lastPrintSeconds = startTic

' Do some processing. Inside a while loop or other loop that will take a long time, add the following...
seconds = (Getthreadinfo(6) - startTic) / Getthreadinfo(7)
If (seconds-lastPrintSeconds) >= 30 Then ' Every 30 seconds or so, print out a progress update
   minutes = seconds / 60
   If seconds <= 120 Then ' If < 2 mins, print out seconds
      Print currDb.Title & " - " & agentName & ": Running for " & Format$(seconds, "##0.0") & " seconds so far."
   Else ' 2+ minutes, print out minutes
      Print currDb.Title & " - " & agentName & ": Running for " & Format$(minutes, "#,##0.0") & " minutes so far."
   End If
   lastPrintSeconds = seconds
End If

' At the bottom of the code (last thing before quitting), add the following...
seconds = (Getthreadinfo(6) - startTic) / Getthreadinfo(7)
minutes = seconds / 60
If seconds <= 120 Then ' If < 2 mins, print out seconds
   Print currDb.Title & " - " & agentName & ": Finished. The code ran for " & Format$(seconds, "##0.0") & " seconds."
Else ' 2+ minutes, print out minutes
   Print currDb.Title & " - " & agentName & ": Finished. The code ran for " & Format$(minutes, "#,##0.0") & " minutes."
End If