Click here to Skip to main content
15,867,835 members
Articles / Programming Languages / C#

High-Performance Timer in C#

Rate me:
Please Sign up or sign in to vote.
4.81/5 (54 votes)
29 Jul 2002CPOL2 min read 591.9K   5.3K   135   57
A C# class to provide exact time measurement in your applications
In this article, you will see a C# class which can provide exact time measurement in applications.

UML Image

Introduction

In some applications, exact time measurement methods are very important. The often used Windows API method GetTickCount() retrieves the number of milliseconds that have elapsed since the system was started, but the GetTickCount() function only achieves resolutions of 1ms and on the other side, they are very imprecise.

So, for exact time measurement, we should find another method.

High resolution timing is supported in Win32 by the QueryPerformanceCounter() and QueryPerformanceFrequency() API methods. This timer functions have much better resolution than the "standard" millisecond-based timer calls, like the GetTickCount() method. On the other side, there is also a little bit overhead when calling this "unmanaged" API methods from C#, but it's better than using the very imprecise GetTickCount() API function.

The first call, QueryPerformanceCounter(), queries the actual value of the high-resolution performance counter at any point. The second function, QueryPerformanceFrequency(), will return the number of counts per second that the high-resolution counter performs. To retrieve the elapsed time of a code section, you have to get the actual value of the high-resolution performance counter immediately before and immediately after the section of code to be timed. The difference of these values would indicate the counts that elapsed while the code executed.

The elapsed time can be computed then, by dividing this difference by the number of counts per second that the high-resolution counter performs (the frequency of the high-resolution timer).

duration = (stop - start) / frequency

For more information about QueryPerformanceCounter and QueryPerformanceFrequency, read the documentation on MSDN.

The Code

The following class implements the functionality of the QueryPerformanceCounter() and QueryPerformanceFrequency() API methods.

C#
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Threading;

namespace Win32
{
    internal class HiPerfTimer
    {
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(
            out long lpPerformanceCount);

        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(
            out long lpFrequency);

        private long startTime, stopTime;
        private long freq;

        // Constructor
        public HiPerfTimer()
        {
            startTime = 0;
            stopTime  = 0;

            if (QueryPerformanceFrequency(out freq) == false)
            {
                // high-performance counter not supported
                throw new Win32Exception();
            }
        }

        // Start the timer
        public void Start()
        {
            // let's do the waiting threads there work
            Thread.Sleep(0);

            QueryPerformanceCounter(out startTime);
        }

        // Stop the timer
        public void Stop()
        {
            QueryPerformanceCounter(out stopTime);
        }

        // Returns the duration of the timer (in seconds)
        public double Duration
        {
            get
            {
                return (double)(stopTime - startTime) / (double) freq;
            }
        }
    }
}

This class is very simple to use. Just create an instance of HiPerfTimer, call Start() to start timing and call Stop() to stop timing. To retrieve the elapsed time, just call the Duration() function and you will get the elapsed time.

The following sample should explain that:

C#
HiPerfTimer pt = new HiPerfTimer();      // create a new PerfTimer object
pt.Start();                              // start the timer
Console.WriteLine("Test\n");             // the code to be timed
pt.Stop();                               // stop the timer
Console.WriteLine("Duration: {0} sec\n", 
     pt.Duration);                       // print the duration of the timed code

The following image shows the output of this sample on my system:

Sample Output

History

  • 26th July, 2002 - Posted (first version)
  • 29th August, 2002 - Added some code for more robustness of the class

Bugs and Comments

If you have any comments or find some bugs, I would love to hear about it and make it better.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: Errors using code Pin
Ri Qen-Sin13-Sep-07 4:41
Ri Qen-Sin13-Sep-07 4:41 
GeneralParameters should be ref long Pin
Axel Rietschin21-Feb-05 16:50
professionalAxel Rietschin21-Feb-05 16:50 
GeneralRe: Parameters should be ref long Pin
Anonymous18-Mar-05 3:39
Anonymous18-Mar-05 3:39 
GeneralRe: Parameters should be ref long Pin
Axel Rietschin18-Mar-05 7:13
professionalAxel Rietschin18-Mar-05 7:13 
QuestionWhat is this returning? Pin
jobobner6-Jan-05 4:52
jobobner6-Jan-05 4:52 
AnswerRe: What is this returning? Pin
Sander van Driel17-Jan-05 7:26
Sander van Driel17-Jan-05 7:26 
GeneralRe: What is this returning? Pin
eyedia7-Feb-11 4:15
eyedia7-Feb-11 4:15 
GeneralInaccurate Timer duration Pin
Joseph McGowan3-Dec-04 4:10
Joseph McGowan3-Dec-04 4:10 
GeneralRe: Inaccurate Timer duration Pin
Anonymous12-Jan-05 8:28
Anonymous12-Jan-05 8:28 
GeneralRe: Inaccurate Timer duration Pin
Liu Junfeng5-Apr-05 3:04
Liu Junfeng5-Apr-05 3:04 
GeneralRe: Inaccurate Timer duration Pin
SuperMegaProg8-Mar-06 7:45
SuperMegaProg8-Mar-06 7:45 
GeneralRe: Inaccurate Timer duration Pin
Brian Clifton11-May-07 11:04
Brian Clifton11-May-07 11:04 
GeneralRe: Inaccurate Timer duration Pin
mbelshe13-Aug-07 11:05
mbelshe13-Aug-07 11:05 
GeneralRe: Inaccurate Timer duration Pin
Brian Clifton26-Sep-07 10:36
Brian Clifton26-Sep-07 10:36 
GeneralOptimization Pin
Anonymous28-Sep-04 6:16
Anonymous28-Sep-04 6:16 
GeneralRe: Optimization Pin
Anonymous28-Sep-04 6:18
Anonymous28-Sep-04 6:18 
GeneralAdding a new propery for split timing Pin
jimboc426-Apr-04 6:01
jimboc426-Apr-04 6:01 
GeneralUsing this in a GPL application Pin
Bjornar Henden18-Sep-03 11:24
Bjornar Henden18-Sep-03 11:24 
GeneralRe: Using this in a GPL application Pin
Daniel Strigl11-Oct-03 2:34
Daniel Strigl11-Oct-03 2:34 
GeneralRe: Using this in a GPL application Pin
Bjornar Henden11-Oct-03 2:52
Bjornar Henden11-Oct-03 2:52 
GeneralEXCELLENT Pin
eggie527-Jul-03 20:51
eggie527-Jul-03 20:51 
GeneralRe: EXCELLENT Pin
Daniel Strigl16-Sep-03 21:52
Daniel Strigl16-Sep-03 21:52 
GeneralRe: EXCELLENT Pin
Jaime Olivares29-Oct-05 8:36
Jaime Olivares29-Oct-05 8:36 
GeneralFor Windows CE.NET Pin
Frank Dzaebel25-Jul-03 4:23
Frank Dzaebel25-Jul-03 4:23 
GeneralRe: For Windows CE.NET Pin
Daniel Strigl25-Jul-03 4:54
Daniel Strigl25-Jul-03 4:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.