суббота, 6 ноября 2010 г.

C# Stopwatch Samples

You want to measure the time required for your programs written in the C# language. This could be for a micro-benchmark or for routine and continuous performance monitoring. This document contains several tips and samples on Stopwatch in the C# language, which is very useful for this purpose.
Use Stopwatch to perform benchmarks of methods and statements.
It is built into the .NET Framework.
It can be used to produce timings per iteration.

Using Stopwatch

First, Stopwatch is a class in the .NET framework that is ideal for timing any operation in your C# programs. You must create Stopwatch as an instance. This makes it useful in multithreaded applications or websites.
=== Program that uses Stopwatch (C#) ===

using System;
using System.Diagnostics;
using System.Threading;

class Program
{
    static void Main()
    {
        // Create new stopwatch
        Stopwatch stopwatch = new Stopwatch();

        // Begin timing
        stopwatch.Start();

        // Do something
        for (int i = 0; i < 1000; i++)
        {
            Thread.Sleep(1);
        }

        // Stop timing
        stopwatch.Stop();

        // Write result
        Console.WriteLine("Time elapsed: {0}",
            stopwatch.Elapsed);
    }
}

=== Output of the program ===

Time elapsed: 00:00:01.0001477
Description. The code includes the "using System.Diagnostics" namespace at the top. This is where the Stopwatch class is defined in the framework. You can see the Stopwatch is created with the new operator in Main.
It calls the Start method. The Start method tells the Stopwatch object to store the current time internally. Essentially, it queries the Windows performance code to find the current tick count of the system. This is extremely accurate.
It executes some slow code. The calls to Thread.Sleep in the loop are not useful and are just for the example. You can ignore them, except to note that they take about one second to complete.
It calls the Stop method. We call the Stop() method on the instance Stopwatch. This tells the Stopwatch to capture the current tick count of the system, also very accurate.
It displays the results. The Console.WriteLine method is called to output the time of the Stopwatch instance. The Elapsed property on Stopwatch is a TimeSpan struct, which overrides the ToString method. It outputs the final line.

Using Stopwatch.StartNew

For your benchmarks or diagnostics code, you probably will prefer the StartNew method. This uses a creational design pattern to return a new instance from a static type method. It eliminates typing and simplifies your code.
=== Program that uses StartNew (C#) ===

class Program
{
    static void Main()
    {
        // Create new stopwatch
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();

        // Do something
        // [omitted]

        // Stop timing
        stopwatch.Stop();

        // Write the results [omitted]
    }
}
Description. We see the StartNew() method is called to create a new instance of StopWatch. For the example, I also show the var syntax, which is a shorthand for the type declaration. Also, I access the System.Diagnostics namespace directly in the statement.

Frequency and IsHighResolution

The Stopwatch class has some static properties and fields on it, including Frequency and IsHighResolution. These can be used to determine the internal configuration of Stopwatch, which depends on the machine and the installation of the .NET runtime.
Stopwatch.Frequency
This is a static field that tells you the number of ticks the Stopwatch uses
per second. You will want to use this to convert an elapsed ticks value, ElapsedTicks,
to a figure in seconds. Additionally, you can find values in milliseconds with this.
[Stopwatch.Frequency Field - MSDN]

Stopwatch.IsHighResolution
This is a static bool that tells you whether the Stopwatch is using high resolution
timing. Stopwatch isn't as useful when this is false.

Using ElapsedTicks

Here we see an example of using the ElapsedTicks instance property on Stopwatch. This is internally a readonly signed System.Int64 value. When you capture ElapsedTicks, you will have to manually do the calculations yourself to convert the values to seconds.
=== Program that uses ElapsedTicks (C#) ===

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        // Create a new Stopwatch
        var stopwatch = Stopwatch.StartNew();

        // Capture the elapsed ticks and write them to the console
        long ticks1 = stopwatch.ElapsedTicks;
        Console.WriteLine(ticks1);

        // Capture the ticks again. This will be a larger value
        long ticks2 = stopwatch.ElapsedTicks;
        Console.WriteLine(ticks2);
    }
}

=== Output of the program ===

11
7092 <-- This means the Console.WriteLine took over 7000 ticks
Description. The example code first creates a new Stopwatch with StartNew, and then captures the ElapsedTicks long property twice. The values are printed to the screen. The Console.WriteLine here was the most expensive operation. It took 7081 ticks.
Stopwatch ticks versus DateTime.Ticks. The ElapsedTicks value from Stopwatch is not normally the same as the DateTime.Ticks value. Stopwatch ticks are far more accurate, when the IsHighResolution property is true. Otherwise, they are equivalent.

Reset method

Here we note that the Reset instance method on Stopwatch effectively erases all the previous timer information to zero. You can usually simply create a new Stopwatch if necessary, which might result in simpler code.

IsRunning property

In this section, we note that Stopwatch also has an IsRunning property. This is only useful if your code uses the Stop or Reset methods in unpredictable ways. For most micro-benchmarks, it is not necessary.

GetTimestamp and static properties

Here in this final example we see possible values of several static properties and methods. The sample shows the Frequency property as well as IsHighResolution and GetTimestamp().
Stopwatch.Frequency:        14318180
Stopwatch.IsHighResolution: True
Stopwatch.GetTimestamp():   174412139895
Description of the values. These values were determined by printing the output of the expressions on the left. The Frequency indicates the number of ticks per second. GetTimeStamp() indicates the total elapsed ticks on the system.

Overhead

In this part, we address the performance impact caused by instantiating a Stopwatch. The Stopwatch class is slower than many operations in C# .NET. This applies when you are using Stopwatch throughout the lifetime of your application for routine monitoring. Using a Stopwatch is more expensive than string concatenations by a factor or two or three in my short test. This means it isn't extravagantly expensive.

Summary

Here we reviewed information about the Stopwatch class in the .NET Framework and C# programming language. Stopwatch is an incredibly useful class to use when performing diagnostics or benchmarks. One way I recommend using Stopwatch is for constant performance monitoring of your applications, not just with benchmarks.

Комментариев нет: