Under the Hood of Stopwatch

Introduction

As all developers, I often need to measure execution time of my own (and not only my own) code. When I was a beginning programmer, I used the DateTime structure for his purpose. Time have passed and I learned about the Stopwatch class and began using it extensively. I think most of you had similar experience. It’s not like I didn’t wonder about how Stopwatch works, at that time, it was simply enough for me to know that Stopwatch measures the elapsed time more precise than DateTime. Now the time has come to explain to myself as well as to the readers how the Stopwatch class actually works and clarify its pros and cons in comparison with DateTIme.

Using DateTime

Using the DateTime structure for measuring code execution time is pretty simple

The DateTime.Now property returns the current local date and time. Instead of the DateTime.Now property, you can use DateTime.UtcNow. The property returns the current date and time in the UTC (Universal Time Coordinate) format.

Few words on the DateTime structure

Perhaps, only few of you wondered what the DateTime structure is really like. The value of the DateTime structure is measured in 100-nanosecond units, that are called ticks, and exact data is represented as a number of ticks starting from 00:00-01-01 AD.

For instance, the number 628539264000000000 stands for 00:00:00, October 6, 1992.

The DateTime contains the only field that contains the number of the past ticks:

It is also worth mentioning that as from NET 2.0, two high-order bits of this field indicate the DateTime type: Unspecfied – not specified, Utc – coordinate time, Local – local time, and the rest 62 bits – the quantity of ticks. We can easily query these two bits with the Kind property.

DateTime Cons

Using the DateTime.Now property for measuring time spans is not a good idea, and that is why:

Calculating of the DateTime.Now property is based on DateTime.UtcNow, i.e. the coordinated time is calculated first, and then the time zone offset is applied to it.

That is why, using DateTime.UtcNow is more correct, since it is calculated much faster:

The problem of the DateTime.Now or DateTime.UtcNow usage lies in the fact that their accuracy is fixed. As I wrote above,

1 tick = 100 nanoseconds = 0.1 microseconds = 0.0001 milliseconds = 0.0000001 seconds

Thus, measuring a time span the length of which is less than the length of one tick is simply impossible. Of course, it is unlikely that you will need it, but still it is a worth knowing thing.

Using the Stopwatch class

The Stopwatch class was introduced in .NET 2.0 and since that time it has never been changed anyhow. It is represented as a set of methods and means that can be used for the exact measurement of the elapsed time.

The public API of the Stopwatch class looks in the following way:

Properties

1. Elapsed – returns total elapsed time;

2. ElapsedMilliseconds – returns total elapsed time in milliseconds;

3. ElapsedTicks – returns total elapsed time in ticks of timer;

4. IsRunning – returns value showing whether the Stopwatch timer is run.

Methods

  1. Reset – stops time span measurement and nulls the elapsed time;
  2. Restart — stops time span measurement, nulls the elapsed time and begins measurement of
    elapsed time;
  3. Start – runs and continues measurement of elapsed time for a span;
  4. StartNew — initializes a new Stopwatch instance, sets the zero value to elapsed time and runs
    measurement of elapsed time;
  5. Stop — stops measurement of the elapsed time for a span.

Fields

  1. Frequency – returns timer frequency as a quantity of ticks per second;
  2. IsHighResolution – specifies, whether timer depends on the high resolution performance counter.

The code using the Stopwatch class for meaurment of the SomeOperation method execution time may look in the following way:

The first two lines may be written more succinctly:

Implementation of Stopwatch

The Stopwatch class is based on HPET (High Precision Event Timer). This timer was introduced by Microsoft for putting the issues of time measurement to rest. The frequency of this timer (min. 10 MHz) is not modified during the system work. For each system, Microsoft determines on its own which devices to use for timer implementation.

The Stopwatch class contains the following fields:

TicksPerMillisecond — defines the quantity of the DateTime ticks per 1 millisecond

TicksPerSecond – defines the quantity of the DateTime ticks per 1 second

isRunning — defines, whether the current instance is run (whether the Start method was called)

startTimeStamp – number of ticks at the time of run

elapsed — total number of the elapsed ticks

tickFrequency – simplifies conversion of the Stopwatch ticks into the DateTime ticks.

The static constructor checks the availability of the HPET timer and, in case of its absence,the Stopwatch frequency is set equal to the DateTime frequency.

The basic operating scenario of this class was shown above: call of the Start method, method time of which must be measured, and then call of the Stop method.

Implementation of the Start method is pretty simple – it remembers the initial quantity of ticks:

It’s worth mentioning, that the call of the Start method on the instance that is already being measured falls flat.

The Stop method is designed in the same simple way:

The call of the Stop method on the stopped instance falls flat as well.

Both methods use the call of GetTimestamp() that returns the quantity of ticks at the moment of the call:

If HPET exists, the Stopwatch ticks differ from the DateTime ticks.

The following code:

looks in the following way on my computer:

Using the Stopwatch ticks for creation of DateTime or TimeSpan is incorrect. The record

will obviously lead to the incorrect results.

To get the DateTime ticks, not Stopwatch ones, we need to use the Elapsed properties and ElapsedMilliseconds, or make the manual conversion. To convert the Stopwatch ticks into the DateTime ticks, the following method is used in the class:

The properties code looks exactly as is it was expected:

Stopwatch Cons

The note to the given class with MSDN states the following: for multiprocessor computers, it does not matter on which processor the stream is executed. However, because of the BIOS errors or in the Hardware Abstraction Layer (HAL), we can get different time calculation results on different processors.

To prevent it, there is the if (elapsed < 0) condition in the Stop method.

I found lots of articles, authors of which faced the problems because of the incorrect work of HPET.

In case of the HPET Stopwatch absence, the DateTime ticks are used. Therefore, its advantage over the explicit usage of DateTime disappears. Besides, time elapsed on the method calls and checks made by Stopwatch should be taken into account, especially it it happens in cycle.

Stopwatch in mono

I became aware of the Stopwatch implementation in mono because I couldn’t rely on the native Microsoft functions for working with HPET.

Stopwatch in mono always uses the DateTime ticks, and therefore it does not have any advantage over explicit usage of DateTume, except better readability.

Environment.TickCount

It is worth mentioning the Environment.TickCount property, that returns time, elapsed since the moment of system loading (in milliseconds).

The value of this property is taken from timer and is stored as a 32-bit signed integer. Thus, if system works continuously, the value of the TickCount property will be increasing from 0 till the Int32.MaxValue value within approximately 24.9 days, and then it will be dropped to the
Int32.MinValue value, which is a negative number, and will begin increasing to null within the next 24,9 days.

The usage of this property corresponds to the call of the GetTickCount() system function, that is very fast, since it simply returns the value corresponding to the value of the corresponding counter. However, its accuracy is quite low (10 milliseconds), since breaks that are generated by the computer realtime clock are used for increasing counter.

Conclusion

The Windows operating system includes many timers (functions allowing to measure time spans). Ones of them are accurate, but not fast (timeGetTime), others are fast but not accurate (GetTickCount, GetSystemTime), and still others are both, fast and accurate, as Microsoft states. The latter ones include the HPET timer and functions allowing to work with it: QueryPerformanceFrequency, QueryPerformanceCounter. The Stopwatch class is actually a manageable wrapper over HPET. The usage of this class has its pros (more accurate measurement of time spans) and cons (errors in BIOS, HALs can lead to incorrect results), and in case of HPET absence, its advantages fade away.

To use or not to use the Stopwatch class – it’s strictly up to you. However, I suppose that its pros prevail over its cons.

Timur Guev

Timur Guev

Timur is an experienced C# developer. For last three years, Timur has been developing the KSS (Kaspesky Subscription Service) highload system with the C#, SQL Server,and Azure technologies. At loose hours, Timur is teaching mathematics.
Timur Guev

Latest posts by Timur Guev (see all)

Timur Guev

Timur is an experienced C# developer. For last three years, Timur has been developing the KSS (Kaspesky Subscription Service) highload system with the C#, SQL Server, and Azure technologies. At loose hours, Timur is teaching mathematics.