The Timing of It All
If I'd had some sort of time measuring facility, I could have kept track of how long the miserable woman spent attempting to clean house. (You can just feel it, can't you? "Myrna, he's attempting to steer this disgusting story into something vaguely technical again!") Over the years, I've concocted my own classes for measuring elapsed time, usually in order to measure comparative timings of programming tasks. The .NET Framework 2.0 adds a bundle of new classes, and rather than creating your own elapsed time measuring tool, you can use the new System.Diagnostics.Stopwatch class to do your timing work. (Funny, I had always named my similar class Stopwatch, with almost identical methods. I published it as part of VB courseware I wrote for AppDev, years ago. I'm wondering if the Framework team got hold of my courseware and copied the class' shape? Nah, I'm guessing not.)
I've often been interested in determining the relative speed of alternate methods of solving a particular programming problem. My own Stopwatch classes used the Win32 API's
GetTickCount (or the more accurate
QueryPerformanceCounter) method to do its job. The .NET Framework 2.0's Stopwatch class does similar work, but without my having to write any code. In addition, the System.Diagnostics.Stopwatch class attempts to use a high-performance system timer if possible (that is, on Windows PCs) and automatically uses a less accurate timer if it must (on mobile devices, for example). I love it when a class I find in the Framework does exactly what I need, in an elegant and well-documented fashion. This class fits that descriptionthe documentation is completely clear, and the members of the class provide all the necessary functionality.
The System.Diagnostics.StopWatch class provides a number of simple instance methods, (
Start,
Stop, and
Reset) all accepting no parameters, all doing exactly what you'd expect. The
Start method gets the timer going, measuring elapsed time. The
Stop method stops measuring elapsed time, but maintains the current count of elapsed time. The
Reset method both stops and resets the elapsed time counter back to
0. The class also provides a shared/static
StartNew method, which both creates a new instance of the class, and starts it measuring elapsed time. This method returns the new instance, like this:
Dim sw As System.Diagnostics.StopWatch = _
StopWatch.StartNew()
You'll also find a shared/static
GetTimeStamp method, which returns the current time stamp, in case you need that information. The class also provides several properties that can return the elapsed time as a TimeSpan (the
Elapsed property), or in milliseconds or timer ticks (
ElapsedMilliseconds and
ElapsedTicks). Finally, you can retrieve the
IsRunning property to determine if the StopWatch instance is currently measuring elapsed time.
In addition, the StopWatch class provides two read-only public fields,
Frequency and
IsHighResolution. Frequency returns the frequency of the timer as the number of ticks per second, indicating the precision and resolution of the timer. The higher this value, the more resolution provided by the timer. On my computer, the value is
3579545, which indicates the number of ticks per second. This number is determined by the hardware and the operating system, and is constant for a given installation. The
IsHighResolution field returns
True if the elapsed time is measured using a high-resolution performance counter. If this value is
False, the class indicates that you're measuring elapsed time using the system timer.
Typically, you'll call the
Start method to start measuring elapsed time, and call the
Stop method to pause or stop measuring. For example, to perform a simple comparison to verify that using the StringBuilder class for multiple string manipulations is more efficient than using the String class directly, you might write code like this:
' This StopWatch code assumes the following imports
' statement has been added to the file:
' Imports System.Text
' Display current StopWatch timer stats,
' create a new StopWatch, and start it
Debug.WriteLine("Frequency: " & Stopwatch.Frequency)
Debug.WriteLine("IsHighResolution: " & _
Stopwatch.IsHighResolution)
Dim sw As Stopwatch = Stopwatch.StartNew()
Dim strOut As String = String.Empty
For i As Integer = 0 To 100
strOut &= "Some new text"
Next
' Stop the timer, and display the
' elapsed ticks
sw.Stop()
Debug.WriteLine("String concatenation: " & _
sw.ElapsedTicks)
' Reset the timer, restart, and repeat
' the test using a StringBuilder
sw.Reset()
sw.Start()
Dim sb As New StringBuilder
For i As Integer = 0 To 100
sb.Append("Some new text")
Next
strOut = sb.ToString()
' Stop the timer and display the results
sw.Stop()
Debug.WriteLine("StringBuilder: " & _
sw.ElapsedTicks)
' On my machine, the results displayed are:
' Frequency: 3579545
' IsHighResolution: True
' String concatenation: 1468
' StringBuilder: 77
As you can see, StringBuilder provides a far more efficient solution when concatenating a large number of strings together, and the StopWatch class makes it easy to determine the behavior. Had I been able to extract my computer from its hiding place (or even been able to extract myself from my seat), I could have easily created a stopwatch to measure the amount of time the unfortunate traveler spent suffering, but I could only imagine during the ordeal. You won't have to suffer the flight, or suffer creating your own StopWatchit's easy and built in, using the .NET Framework 2.0.