65.9K
CodeProject is changing. Read more.
Home

High Resolution Elapsed Timer

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (9 votes)

Dec 13, 2001

viewsIcon

103125

downloadIcon

825

A simple high resolution timer class to help time code blocks.

Introduction

The motivation for this came when I needed to time sections of code while analyzing performance issues. The existing timers did not provide the necessary granularity to accurately measure execution times in microseconds. So I ended up creating this simple class to do the timing.

Here's the class declaration:

// HighResElapsedTimer.h: interface for the HighResElapsedTimer class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(HIGHRESELAPSEDTIMER_H_INCLUDED_)
#define HIGHRESELAPSEDTIMER_H_INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// File:  HighResElapsedTimer.h
// Author:  Chen Venkataraman (venkatar@sig.com)
// Date:  Wed Dec 6, 2001
//
// Purpose: 
//  For determing elapsed time details during execution of code blocks 
//  (initially for debug builds only)
//
//  Sample usage:
//
//  {
//    #ifdef _DEBUG
//     HighResElapsedTimer  elapsedTime("block id");
//    #endif
//
//    ... rest of the code block
//  }
//
//    At the end of the above block, trace msg of the form
//    "block id : Elapsed time - xxxx.xxx microseconds" is spit out

#ifdef _DEBUG

class HighResElapsedTimer  
{
public:
  HighResElapsedTimer(const CString& strName) : m_strName(strName)
  {
    if (m_llFrequency == 0)      // frequency value not yet set
    {
      LARGE_INTEGER  liFrequency;

      QueryPerformanceFrequency(&liFrequency);
      m_llFrequency = liFrequency.QuadPart;
    }

    QueryPerformanceCounter(&m_llCounter);
  }

  virtual ~HighResElapsedTimer()
  {
    LARGE_INTEGER    liNow;
    QueryPerformanceCounter(&liNow);
    double duration = (double)
      (liNow.QuadPart - m_llCounter.QuadPart)/m_llFrequency;

    TRACE(_T("%s : Elapsed time = %.3lf microseconds\n"), 
                                      m_strName, duration);
  }

private:
  CString      m_strName;
  LARGE_INTEGER  m_llCounter;

private:
  static LONGLONG  m_llFrequency; 
  // Frequency setting is based hardware clock which doesn't
  // does change - so we want to set this only once

private:
  HighResElapsedTimer(const HighResElapsedTimer&);
  HighResElapsedTimer& operator=(const HighResElapsedTimer&);
};

#endif  // _DEBUG

#endif  // !defined(HIGHRESELAPSEDTIMER_H_INCLUDED_)

... and here is the implementation.

// HighResElapsedTime.cpp: implementation of the HighResElapsedTime class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HighResElapsedTimer.h"

#ifdef _DEBUG

/* static */
LONGLONG HighResElapsedTimer::m_llFrequency = 0;

#endif    // _DEBUG

Since I was timing the code execution only during debug builds, I've guarded the code using #ifdef _DEBUG's & used TRACE for output. If you want to time release builds or output differently, it should be fairly trivial to do so.

I've tested this only on NT4 SP6a & hopefully it will work on Win95 m/cs also.