Re: Displaying a large amount of data quickly (VB6)
- From: "Karl E. Peterson" <karl@xxxxxxxx>
- Date: Fri, 15 Jul 2005 13:46:19 -0700
Hi Tom --
>>> It kinda looks like my suspicion might be correct - that anything
>>> involving a loop of VB code would be too slow.
>>
>> I still think you're wrong about Join being faster. It's possible I
>> suppose, but I'd sure be interested to know if that StringBuilder
>> class I pointed you to couldn't do it quicker.
>
> Ken, you piqued my interest, so I tried it out.
>
> I added this in front of the timed sections:
>
> datastr = "C:\Program files\Microsoft\Office\Office10\WinWOrd.exe"
> ReDim bigarray(Loops) As String
> For i = 1 To Loops
> bigarray(i) = datastr
> Next i
>
> In the "standard append" section, I did this:
>
> tmr.Reset
> sTmp = Join(bigarray, vbCrLf)
> d2 = tmr.Elapsed
>
> In the "stringbuilder append" section, I changed it to this:
>
> For i = 1 To Loops
> sb.Append bigarray(i)
> sb.Append vbCrLf
> Next i
>
> The results:
>
> 5000 loops: std append: 2 sb: 27
> 10000 loops: std append: 4 sb: 61
> 25000 loops: std append: 8 sb: 183
>
> It kinda looks like the Join is, like, way faster.
>
> What do you think? Did I run a valid test?
Wow. I had some _real_ trouble with your results, so I (naturally <g>) had to run
some myself. Learned something today! Join *is* fast! Here's the test I ran:
Private Sub RunBench()
Dim dat() As String
Dim i As Long, elements As Long
Dim Buffer As String
Dim stp As New CStopWatch
Dim jn As CStringBuilder
Dim e As Long, e0 As Long
Const elLength As Long = 70
For elements = 25000 To 250000 Step 25000
Feedback "Array elements: " & elements
' Loop overhead
stp.Reset
For i = 1 To elements
' nothing
Next i
e0 = stp.Elapsed
Feedback "Loop overhead: " & e0
' Build array of strings
stp.Reset
Buffer = String$(elLength, "*")
ReDim dat(1 To elements) As String
For i = 1 To elements
dat(i) = Buffer
Next i
e = stp.Elapsed
Feedback "Array construction: " & e - e0
' Test Join
stp.Reset
Buffer = Join(dat, vbCrLf)
e = stp.Elapsed
Feedback "Join concatentation: " & e
' Test StrBldr1, complete
stp.Reset
Set jn = New CStringBuilder
With jn
.Capacity = (elLength + 2) * (elements * 2)
For i = 1 To elements
.Append dat(i) & vbCrLf
Next i
End With
e = stp.Elapsed
Set jn = Nothing
Feedback "StringBuilder: " & e - e0
Next elements
End Sub
What I found, after compiling with all optimizations(!), was that Join was ~3x as
fast as my CStringBuilder class. Here are the exact results:
Compiled: True
Array elements: 25000
Loop overhead: 0
Array construction: 17
Join concatentation: 11
StringBuilder: 30
Array elements: 50000
Loop overhead: 0
Array construction: 50
Join concatentation: 19
StringBuilder: 58
Array elements: 75000
Loop overhead: 0
Array construction: 83
Join concatentation: 29
StringBuilder: 92
Array elements: 100000
Loop overhead: 0
Array construction: 144
Join concatentation: 47
StringBuilder: 126
Array elements: 125000
Loop overhead: 0
Array construction: 174
Join concatentation: 60
StringBuilder: 157
Array elements: 150000
Loop overhead: 0
Array construction: 215
Join concatentation: 66
StringBuilder: 189
Array elements: 175000
Loop overhead: 0
Array construction: 263
Join concatentation: 89
StringBuilder: 231
Array elements: 200000
Loop overhead: 0
Array construction: 315
Join concatentation: 94
StringBuilder: 250
Array elements: 225000
Loop overhead: 0
Array construction: 339
Join concatentation: 118
StringBuilder: 297
Array elements: 250000
Loop overhead: 0
Array construction: 365
Join concatentation: 123
StringBuilder: 311
Well, naturally, I wasn't very thrilled about that, so I added a second StringBuilder
test such that its internal results buffer was built outside the timer:
' Test StrBldr1, omitting buffer construction
Set jn = New CStringBuilder
With jn
.Capacity = (elLength + 2) * (elements * 2)
stp.Reset
For i = 1 To elements
.Append dat(i) & vbCrLf
Next i
e = stp.Elapsed
End With
Set jn = Nothing
Feedback "StringBuilder: " & e - e0
This got more interesting:
Array elements: 100000
Loop overhead: 0
Array construction: 138
Join concatentation: 42
StringBuilder: 130
StringBuilder: 63
Array elements: 250000
Loop overhead: 0
Array construction: 385
Join concatentation: 130
StringBuilder: 341
StringBuilder: 171
Now, Join is only marginally faster. I think I need to take a closer look at how my
buffer is being allocated in the class! This is probably the clearest example
possible why preallocating the entire buffer is critical, when time is of the
essence. If I remove the preallocation altogether, with something like this:
' Test StrBldr1, complete
stp.Reset
Set jn = New CStringBuilder
With jn
' *** .Capacity = (elLength + 2) * (elements * 2) ***
For i = 1 To elements
.Append dat(i) & vbCrLf
Next i
End With
e = stp.Elapsed
Set jn = Nothing
Feedback "StringBuilder: " & e - e0
The results are in the more depressing category you responded with originally:
Array elements: 250000
Loop overhead: 0
Array construction: 366
Join concatentation: 125
StringBuilder: 1169
Anyway, it seems clear, *if* your strings are already in an array, Join is the way to
go. (Although, to remain VB5 friendly and given the minimal [sub-1/4 second] timing
differences on 250K strings, I'd probably stick with StringBuilder, just to keep the
code more portable.)
Thanks... Karl
--
Working Without a .NET?
http://classicvb.org/petition
.
- References:
- Displaying a large amount of data quickly (VB6)
- From: Tom Bates
- Re: Displaying a large amount of data quickly (VB6)
- From: Tom Bates
- Re: Displaying a large amount of data quickly (VB6)
- From: Rick Rothstein
- Re: Displaying a large amount of data quickly (VB6)
- From: Tom Bates
- Re: Displaying a large amount of data quickly (VB6)
- From: Karl E. Peterson
- Re: Displaying a large amount of data quickly (VB6)
- From: Tom Bates
- Displaying a large amount of data quickly (VB6)
- Prev by Date: Re: Displaying a large amount of data quickly (VB6)
- Next by Date: Re: Server side Winsock Control, ports and firewalls
- Previous by thread: Re: Displaying a large amount of data quickly (VB6)
- Next by thread: Re: Displaying a large amount of data quickly (VB6)
- Index(es):