[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: [ANN] LuaProfiler 2.0
- From: "Michael Cumming" <Mike.C@...>
- Date: Tue, 14 Jun 2005 21:28:47 -0500
Here is a c++ class that will help ....
// CPerfTimer - a simple Win32 performance counter wrapper
// by Dean Wyant dwyant@mindspring.com
/*
This class is simple to use. Just declare a variable(s) as type
CPerfTimer,
call Start() to start timimg and call Stop() to stop timimg. You can
pause a
timer by calling Stop() and then you can call Start() to resume.
Retrieve the
elapsed time by calling an Elapsed..() function. Assignment, addition,
subtraction and comparison are supported. There are a few information
calls
available also. All calls except Start and Stop can be performed on a
timer
without stopping it.
*/
#ifndef __PERFTIMER_H__
#define __PERFTIMER_H__
#include <windows.h>
class CPerfTimer
{
public:
CPerfTimer(BOOL bStart = FALSE) {Init(bStart);}
CPerfTimer(const CPerfTimer& Src);
virtual ~CPerfTimer() {;}
void Start(BOOL bReset = FALSE); // Start from current value or
optionally from 0
void Stop(); // Stop timing. Use Start
afterwards to continue.
BOOL IsRunning(); // Returns FALSE if stopped.
BOOL IsSupported(); // Returns FALSE if performance
counter not supported.
// Call after constructing at least
one CPerfTimer
const double Resolution(); // Returns timer resolution in
seconds
const double Resolutionms(); // Returns timer resolution in
milliseconds
const double Resolutionus(); // Returns timer resolution in
microseconds
const double Elapsed(); // Returns elapsed time in seconds
const double Elapsedms(); // Returns elapsed time in
milliseconds
const double Elapsedus(); // Returns elapsed time in
microseconds
const CPerfTimer& operator=(const CPerfTimer& Src); // Assignment
operator
// Math operators
CPerfTimer operator+(const CPerfTimer& Src) const;
CPerfTimer operator-(const CPerfTimer& Src) const;
const CPerfTimer& operator+=(const CPerfTimer& Src);
const CPerfTimer& operator-=(const CPerfTimer& Src);
// For time in seconds
CPerfTimer operator+(const double Secs) const;
CPerfTimer operator-(const double Secs) const;
const CPerfTimer& operator+=(const double Secs);
const CPerfTimer& operator-=(const double Secs);
// Boolean comparison operators
BOOL operator<(const CPerfTimer& Src);
BOOL operator>(const CPerfTimer& Src);
BOOL operator<=(const CPerfTimer& Src);
BOOL operator>=(const CPerfTimer& Src);
// For time in seconds
BOOL operator<(const double Secs);
BOOL operator>(const double Secs);
BOOL operator<=(const double Secs);
BOOL operator>=(const double Secs);
virtual void Lock() const {;} // Override for thread safe
operation
virtual void Unlock() const {;} // Override for thread safe
operation
protected:
void Init(BOOL bStart);
void Copy(const CPerfTimer& Src);
private:
__int64 m_Start;
static __int64 m_Freq; // does not change while system is running
static __int64 m_Adjust; // Adjustment time it takes to Start and Stop
};
class CPerfTimerT : public CPerfTimer
{ // You only need to use types of this class if a timer is going to be
shared between threads
public:
CPerfTimerT(BOOL bStart = FALSE)
{
m_hMutex = CreateMutex(NULL,FALSE,"");
Init(bStart);
}
CPerfTimerT(const CPerfTimerT& Src)
{
m_hMutex = CreateMutex(NULL,FALSE,"");
Copy(Src);
}
CPerfTimerT(const CPerfTimer& Src)
{
m_hMutex = CreateMutex(NULL,FALSE,"");
Copy(Src);
}
virtual ~CPerfTimerT()
{ CloseHandle(m_hMutex); }
const CPerfTimerT& operator=(const CPerfTimerT& Src) // Assignment
operator
{
Copy(Src);
return *this;
}
virtual void Lock() const { WaitForSingleObject(m_hMutex,10000); }
virtual void Unlock() const { ReleaseMutex(m_hMutex); }
private:
HANDLE m_hMutex;
};
inline void CPerfTimer::Init(BOOL bStart)
{
if (!m_Freq)
{ // Initialization should only run once
QueryPerformanceFrequency((LARGE_INTEGER *)&m_Freq);
if (!m_Freq)
m_Freq = 1; // Timer will be useless but will not cause divide by
zero
m_Start = 0;
m_Adjust = 0;
Start(); // Time a Stop
Stop();
m_Adjust = m_Start;
}
// This is the only part that normally runs
m_Start = 0;
if (bStart)
Start();
}
inline CPerfTimer::CPerfTimer(const CPerfTimer& Src)
{
Copy(Src);
}
inline void CPerfTimer::Copy(const CPerfTimer& Src)
{
if (&Src == this)
return; // avoid deadlock if someone tries to copy it to itself
Src.Lock();
Lock();
m_Start = Src.m_Start;
Unlock();
Src.Unlock();
}
inline void CPerfTimer::Start(BOOL bReset)
{ // Start from current value or optionally from 0
__int64 i;
QueryPerformanceCounter((LARGE_INTEGER *)&i);
Lock();
if ((!bReset) && (m_Start < 0))
m_Start += i; // We are starting with an accumulated time
else
m_Start = i; // Starting from 0
Unlock();
}
inline void CPerfTimer::Stop()
{ // Stop timing. Use Start afterwards to continue
Lock();
if (m_Start <= 0)
{
Unlock();
return; // Was not running
}
__int64 i;
QueryPerformanceCounter((LARGE_INTEGER *)&i);
m_Start += -i; // Stopped timer keeps elapsed timer ticks as
a negative
if (m_Start < m_Adjust) // Do not overflow
m_Start -= m_Adjust; // Adjust for time timer code takes to run
else
m_Start = 0; // Stop must have been called directly after
Start
Unlock();
}
inline BOOL CPerfTimer::IsRunning()
{ // Returns FALSE if stopped.
Lock();
BOOL bRet = (m_Start > 0); // When < 0, holds elpased clicks
Unlock();
return bRet;
}
inline const double CPerfTimer::Elapsed()
{ // Returns elapsed time in seconds
CPerfTimer Result(*this);
Result.Stop();
return (double)(-Result.m_Start)/(double)m_Freq;
}
inline const double CPerfTimer::Elapsedms()
{ // Returns elapsed time in milliseconds
CPerfTimer Result(*this);
Result.Stop();
return (-Result.m_Start*1000.0)/(double)m_Freq;
}
inline const double CPerfTimer::Elapsedus()
{ // Returns elapsed time in microseconds
CPerfTimer Result(*this);
Result.Stop();
return (-Result.m_Start * 1000000.0)/(double)m_Freq;
}
// Assignment operator
inline const CPerfTimer& CPerfTimer::operator=(const CPerfTimer& Src)
{
Copy(Src);
return *this;
}
// Math operators
inline CPerfTimer CPerfTimer::operator+(const CPerfTimer& Src) const
{
CPerfTimer Result(*this);
Result += Src;
return Result;
}
inline CPerfTimer CPerfTimer::operator-(const CPerfTimer& Src) const
{
CPerfTimer Result(*this);
Result -= Src;
return Result;
}
inline const CPerfTimer& CPerfTimer::operator+=(const CPerfTimer& Src)
{
CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not
stopped
SrcStop.Stop();
Lock();
m_Start += SrcStop.m_Start;
Unlock();
return *this;
}
inline const CPerfTimer& CPerfTimer::operator-=(const CPerfTimer& Src)
{
CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not
stopped
SrcStop.Stop();
Lock();
m_Start -= SrcStop.m_Start;
Unlock();
return *this;
}
// For time in seconds
inline CPerfTimer CPerfTimer::operator+(const double Secs) const
{
CPerfTimer Result(*this);
Result += Secs;
return Result;
}
inline CPerfTimer CPerfTimer::operator-(const double Secs) const
{
CPerfTimer Result(*this);
Result += Secs;
return Result;
}
inline const CPerfTimer& CPerfTimer::operator+=(const double Secs)
{
Lock();
m_Start -= (__int64)(Secs*(double)m_Freq);
Unlock();
return *this;
}
inline const CPerfTimer& CPerfTimer::operator-=(const double Secs)
{
Lock();
m_Start += (__int64)(Secs*(double)m_Freq);
Unlock();
return *this;
}
// Boolean comparison operators
inline BOOL CPerfTimer::operator<(const CPerfTimer& Src)
{
BOOL bRet;
CPerfTimer Temp(Src);
Lock();
if (m_Start <= 0)
{
Temp.Stop();
bRet = (m_Start > Temp.m_Start);
Unlock();
return bRet;
}
else
if (Temp.m_Start > 0)
{
bRet = (m_Start < Temp.m_Start);
Unlock();
return bRet;
}
else
{
Unlock();
CPerfTimer ThisStop(*this);
ThisStop.Stop();
return (ThisStop.m_Start > Temp.m_Start);
}
}
inline BOOL CPerfTimer::operator>(const CPerfTimer& Src)
{
BOOL bRet;
CPerfTimer Temp(Src);
Lock();
if (m_Start <= 0)
{
Temp.Stop();
bRet = (m_Start < Temp.m_Start);
Unlock();
return bRet;
}
else
if (Temp.m_Start > 0)
{
bRet = (m_Start > Temp.m_Start);
Unlock();
return bRet;
}
else
{
Unlock();
CPerfTimer ThisStop(*this);
ThisStop.Stop();
return (ThisStop.m_Start < Temp.m_Start);
}
}
inline BOOL CPerfTimer::operator<=(const CPerfTimer& Src)
{
return !(*this > Src);
}
inline BOOL CPerfTimer::operator>=(const CPerfTimer& Src)
{
return !(*this < Src);
}
// For time in seconds
inline BOOL CPerfTimer::operator<(const double Secs)
{
BOOL bRet;
Lock();
if (m_Start <= 0)
{
bRet = (m_Start > (__int64)(-Secs*(double)m_Freq));
Unlock();
return bRet;
}
else
{
Unlock();
CPerfTimer ThisStop(*this);
ThisStop.Stop();
return (ThisStop.m_Start > (__int64)(-Secs*(double)m_Freq));
}
}
inline BOOL CPerfTimer::operator>(const double Secs)
{
BOOL bRet;
Lock();
if (m_Start <= 0)
{
bRet = (m_Start < (__int64)(-Secs*(double)m_Freq));
Unlock();
return bRet;
}
else
{
Unlock();
CPerfTimer ThisStop(*this);
ThisStop.Stop();
return (ThisStop.m_Start < (__int64)(-Secs*(double)m_Freq));
}
}
inline BOOL CPerfTimer::operator<=(const double Secs)
{
return !(*this > Secs);
}
inline BOOL CPerfTimer::operator>=(const double Secs)
{
return !(*this < Secs);
}
#endif //__PERFTIMER_H__
And
// CPerfTimer - a simple Win32 performance counter wrapper
// by Dean Wyant dwyant@mindspring.com
#include "stdafx.h"
#include "PerfTimer.h"
// Declare and initialize static member vars that get set only once and
never change
__int64 CPerfTimer::m_Freq = 0;
__int64 CPerfTimer::m_Adjust = 0;
// All functions defined inline for speed. After all, the performance
counter is
// supposed to be able to time very short events fairly accurately.
BOOL CPerfTimer::IsSupported()
{ // Returns FALSE if performance counter not supported.
// Call after constructing at least one CPerfTimer
return (m_Freq > 1);
}
const double CPerfTimer::Resolution()
{ // Returns timer resolution in seconds
return 1.0/(double)m_Freq;
}
const double CPerfTimer::Resolutionms()
{ // Returns timer resolution in milliseconds
return 1000.0/(double)m_Freq;
}
const double CPerfTimer::Resolutionus()
{ // Returns timer resolution in microseconds
return 1000000.0/(double)m_Freq;
}