'Concat Timer: Option Public Option Explicit Class Concat Private concatString As String Private elapsedTime As Single Public Function GetFinalString () As String GetFinalString = concatString End Function Public Function GetTime () As Single GetTime = elapsedTime End Function Public Function DoConcat (txt As String, count As Long) As Single Dim startTime As Single Dim i As Long startTime = Timer() For i = 1 To count Call PrivateConcat(txt) Next Call FinalizeString() elapsedTime = Round( Timer() - startTime, 4 ) DoConcat = elapsedTime End Function '** override these methods in subclasses Private Sub PrivateConcat (txt As String) concatString = concatString & txt End Sub Private Sub FinalizeString () '** nothing to do in the base class End Sub End Class Class RichTextConcat As Concat Private doc As NotesDocument Private item As NotesRichTextItem Public Sub New () Dim s As New NotesSession Set doc = s.CurrentDatabase.CreateDocument Set item = doc.CreateRichTextItem( "body" ) End Sub Private Sub PrivateConcat (txt As String) Call item.AppendText( txt ) End Sub Private Sub FinalizeString () concatString = item.GetUnformattedText() End Sub End Class Class StreamConcat As Concat Private stream As NotesStream Public Sub New () Dim s As New NotesSession Set stream = s.CreateStream End Sub Private Sub PrivateConcat (txt As String) Call stream.WriteText( txt ) End Sub Private Sub FinalizeString () stream.Position = 0 concatString = stream.ReadText End Sub End Class Class StringBufferConcat As Concat Private sb As StringBuffer Public Sub New () Set sb = New StringBuffer(32000) End Sub Private Sub PrivateConcat (txt As String) Call sb.append( txt ) End Sub Private Sub FinalizeString () concatString = sb.toString() End Sub End Class Class StringBuffer '** This is a class that provides basic StringBuffer functionality '** in LotusScript (which is more efficient if you are doing a '** whole bunch of String concatenations). You should probably '** add some error handling, and take a look at the methods in '** the Java StringBuffer class to see if there's any other '** functionality you'd like to emulate. '** '** version 1.0 '** Julian Robichaux -- http://www.nsftools.com '** August 9, 2004 Private tempArray() As String Private buffer As String Private pos As Integer Private startSize As Integer Private upperB As Integer Private maxSize As Integer Sub New (startSize As Integer) '** startSize is just the initial size of the internal array, '** which will be doubled every time you run out of '** space in the internal array (16 is a good number '** to use here) Me.startSize = startSize '** if you have to use r5Join in the toString method, '** set maxSize to ~ 3000; otherwise (if you're using '** the Join function in Notes 6 or higher) you can set '** maxSize as big of an Integer as you'd like (I use 32000) maxSize = 32000 Me.resetArray(startSize) End Sub '** return the contents of the StringBuffer as a String Public Function toString () As String '** if this has to be compatible with Notes R5 or lower, use: 'toString = buffer & r5Join(tempArray, "") '** for Notes 6 and higher, you can use: toString = buffer & Join(tempArray, "") End Function '** append any kind of variable that can be converted to a String Public Sub append (v As Variant) If (pos > upperB) Then buffer = Me.toString Me.resetArray(Clng(upperB) * 2) End If tempArray(pos) = Cstr(v) pos = pos + 1 End Sub '** use this if you want to clear the StringBuffer Public Sub erase () Me.resetArray(startSize) buffer = "" End Sub Private Sub resetArray (size As Long) Select Case size Case Is < 0 : upperB = 0 Case Is > maxSize : upperB = maxSize Case Else : upperB = size End Select Redim tempArray(0 To upperB) As String pos = 0 End Sub Private Function r5Join (arr As Variant, delim As String) As String '** this is a version of the ND6 Join function (also called the '** Implode function), for use with Notes R5 or lower On Error Goto processError Dim i As Integer Dim lb As Integer, ub As Integer Dim delimLen As Integer Dim returnString As String lb = Lbound(arr) ub = Ubound(arr) For i = lb To ub r5Join = r5Join + Cstr(arr(i)) + delim Next processError: Exit Function End Function End Class Sub Initialize '** Increase the number of concatenations by 5,000 every time '** we run the agent. We'll always want to use "clean" agent runs '** instead of increasing the iterations in a loop, in order to clean '** the memory and get more accurate runtimes. So we'll just have '** to keep running the agent over and over again. The best way to '** do it is actually to run the same test with the same number of '** iterations several times (over several different agent runs) and '** average the results, but the way the number spreads end up '** looking it really doesn't matter. Dim session As New NotesSession Dim doc As NotesDocument Dim iterations As Long Set doc = session.SavedData If (Cstr(doc.Iterations(0)) = "") Then iterations = 0 Else iterations = doc.Iterations(0) End If iterations = iterations + 5000 doc.Iterations = iterations Call doc.Save(True, False) '** Here's the string we'll be appending over and over. Dim txt As String txt = "test" '** These are the different types of concatenations we are testing. '** In a perfect world, we'd do several tests using a different order '** of the concatenation types each time, to make sure that the '** early types didn't have an adverse timing effect on the later types. '** However, in limited testing this really didn't matter. Dim arr(0 To 3) As Concat Set arr(0) = New Concat() Set arr(1) = New RichTextConcat() Set arr(2) = New StreamConcat() Set arr(3) = New StringBufferConcat() '** Write the output to a CSV file, for spreadsheet graphing when we're done. Dim fileName As String Dim fileNum As Integer fileName = "c:\ConcatTest.csv" fileNum = Freefile() Open fileName For Append As fileNum Dim outputString As String, pct As String Dim baseTime As Single, eTime As Single outputString = Cstr(iterations) Forall c In arr eTime = c.DoConcat(txt, iterations) If (baseTime = 0) Then baseTime = eTime If (eTime > 0) Then pct = Round( ((baseTime / eTime) * 100) - 100, 2) & "%" Else pct = "NaN%" End If outputString = outputString & "," & eTime & "," & pct End Forall Print outputString Print #fileNum, outputString Close fileNum End Sub