Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Erratic result

76 views
Skip to first unread message

Kurt

unread,
Aug 6, 2003, 2:04:30 PM8/6/03
to
I have a console app that doe a simple timing comparison
between using the String and StringBuilder objects. It
worked fine initially and then I added two lines to
simply display the tick count of answer1 and answer2.
Now some times it works; "x is nnn times faster than y"
but then sometimes it doesn't "x is infinity times faster
than y". I've tried to isolate just how and when I get
the affect, but have been unable to. While this is a
trivial example, it is a bit concerning to see shifting
behaviour like this in such a small test.

thx
Kurt

Option Strict On
Module Module1
Sub Main()
Console.WriteLine("Please wait calculating with
50000 character strings ....")
Dim i As Integer
Dim StartTime As New DateTime()
Dim EndTime As New DateTime()
StartTime = DateTime.Now()
Dim theText As New System.Text.StringBuilder()
For i = 1 To 50000
theText = theText.Append("A")
Next
EndTime = DateTime.Now
Dim answer1, answer2 As Long
answer1 = EndTime.Ticks() - StartTime.Ticks
() 'number of 100 nanosecond pulses
StartTime = DateTime.Now()
Dim aString As String
For i = 1 To 50000
aString = aString & "A"
Next
EndTime = DateTime.Now
answer2 = (EndTime.Ticks() - StartTime.Ticks
()) 'number of 100 nanosecond pulses
'Console.WriteLine("StringBuilder Ticks was " &
answer1 & ".")
'Console.WriteLine("String Ticks was " & answer2
& ".")
Console.WriteLine("StringBuilder was " &
answer2 / answer1 & " times faster.")
Console.ReadLine()
End Sub
End Module

Jeremy Cowles

unread,
Aug 6, 2003, 2:24:35 PM8/6/03
to
Kurt,

My assumption is that you are using Ticks, and a Double to store the value.
Is that correct? The problem is that your code is executing faster than the
Ticks can count, or you have a division error. At any rate, you should be
using the Performance api functions (i cant remember the names now) because
they are much more accurate and percise than Ticks or other built-in methods
of measuring time. The down-side of this is that you don't accuratly time
your execution because you have the added overhead of calling an API method.
The best way to measure preformance is to use performance counters (there is
an example of how to do this in the .NET 2003 tour video). For better
results to your questions, try posting in the .NET performance group:

news://msnews.microsoft.com/microsoft.public.dotnet.framework.performance


HTH,
Jeremy


"Kurt" <kska...@comcast.net> wrote in message
news:006b01c35c45$2eda1990$a601...@phx.gbl...

Kurt

unread,
Aug 6, 2003, 3:40:08 PM8/6/03
to
Jeremy,

Thanks for the input. Let me clarify. I'm really not
concerned with the actual performance here, (although
your recommendations will prove useful down the road for
me.) It's just a simple illustration. The problem is
that answer1 should NEVER be 0. The ticks are measured
in 100ns pulses. When the program works as expected,
stringbuilder shows to be about 430 times faster, then I
run again and answer1 starts showing up at 0. I suspect
I am looking at a bug, but would like some input from
others before submitting to whomever I should be
submitting it to.

thx
Kurt

>.
>

Jeremy Cowles

unread,
Aug 7, 2003, 8:22:02 AM8/7/03
to
"Kurt" <kska...@comcast.net> wrote in message
news:072601c35c52$8ae87670$a101...@phx.gbl...

> Jeremy,
>
> Thanks for the input. Let me clarify. I'm really not
> concerned with the actual performance here, (although
> your recommendations will prove useful down the road for
> me.) It's just a simple illustration. The problem is
> that answer1 should NEVER be 0. The ticks are measured
> in 100ns pulses. When the program works as expected,
> stringbuilder shows to be about 430 times faster, then I
> run again and answer1 starts showing up at 0. I suspect
> I am looking at a bug, but would like some input from
> others before submitting to whomever I should be
> submitting it to.

No, it's just the JIT compiler. The first run is slow (depending on what you
are doing), and subsequent runs are incredibly fast. So when you try to
time it with Ticks, it is running too fast to be measured. Try running your
test in a longer loop (try 1,000,000), that should solve your problem
(amplify your results).

HTH,
Jeremy

Armin Zingler

unread,
Aug 8, 2003, 9:19:05 AM8/8/03
to
"Kurt" <kska...@comcast.net> schrieb

> Jeremy,
>
> Thanks for the input. Let me clarify. I'm really not
> concerned with the actual performance here, (although
> your recommendations will prove useful down the road for
> me.) It's just a simple illustration. The problem is
> that answer1 should NEVER be 0. The ticks are measured
> in 100ns pulses. When the program works as expected,
> stringbuilder shows to be about 430 times faster, then I
> run again and answer1 starts showing up at 0. I suspect
> I am looking at a bug, but would like some input from
> others before submitting to whomever I should be
> submitting it to.

Ticks is the unit, not the resolution! The resolution might be 10
milliseconds, so if the first loop takes less time, you might get the same
number of ticks after the loop.

Try this to find out the resolution of the ticks property:

Dim i1, i2 As Long
i1 = Date.Now.Ticks
Do
i2 = Date.Now.Ticks
Loop Until i2 <> i1
MsgBox("Resolution: " _
& ((i2 - i1) / 10000000).ToString("0.000000000") _
& " seconds")

I get a resolution of 1/100 second.

Make a longer loop taking several seconds (as already suggested), or use
Environment.Tickcount instead or one of the high performance counters.


Here's a high-performance stopwatch:


'© Armin Zingler (2003)

Public NotInheritable Class HPCounter

Private Shared m_Frequency As Long

Shared Sub New()
Win32.QueryPerformanceFrequency(m_Frequency)
End Sub

Private Sub New()
End Sub

Public Shared ReadOnly Property Counter() As Long
Get
Win32.QueryPerformanceCounter(Counter)
End Get
End Property

Public Shared ReadOnly Property Frequency() As Long
Get
Return m_Frequency
End Get
End Property

Public Shared ReadOnly Property TotalSeconds() As Double
Get
Return Counter / m_Frequency
End Get
End Property

End Class

Public Class HPStopwatch
Private m_StartCounter, m_EndCounter As Long
Private m_IsRunning As Boolean

Private Shared m_Stopwatch As New HPStopwatch

Public Shared ReadOnly Property DefaultWatch() As HPStopwatch
Get
Return m_Stopwatch
End Get
End Property

Public Sub Start()
m_StartCounter = HPCounter.Counter
m_IsRunning = True
End Sub

Public ReadOnly Property Counter() As Long
Get
If m_IsRunning Then
Return HPCounter.Counter - m_StartCounter
Else
Return m_EndCounter - m_StartCounter
End If
End Get
End Property

Public ReadOnly Property TotalSeconds() As Double
Get
Return Me.Counter / HPCounter.Frequency
End Get
End Property

Public ReadOnly Property IsRunning() As Boolean
Get
Return m_IsRunning
End Get
End Property

Public Sub [Stop]()
m_EndCounter = HPCounter.Counter
m_IsRunning = False
End Sub
End Class

--
Armin

0 new messages