Hi, I'm interested in measuring a specific point in time down to the nanosecond using c++ in windows. Is this possible? If it isn't, is it possible to get the specific time in microseconds at least? Any library should do, unless I suppose it's possible with managed code. thanks
Windows has a high-performance counter API
You need to get the ticks form QueryPerformanceCounter
and divide by the frequency of the processor, provided by QueryPerformanceFrequency
.
LONG_INTEGER frequency;
if (::QueryPerformanceFrequency(&frequency) == FALSE)
throw "foo";
LONG_INTEGER start;
if (::QueryPerformanceCounter(&start) == FALSE)
throw "foo";
// Calculation.
LONG_INTEGER end;
if (::QueryPerformanceCounter(&end) == FALSE)
throw "foo";
double interval = static_cast<double>(end - start) / frequency;
This interval
should be in seconds.
You can use the Performance Counter API as Konrad Rudolf proposed, but should be warned that it is based on the CPU frequency. This frequency is not stable when e.g. a power save mode is enabled. If you want to use this API, make sure the CPU is at a constant frequency.
Otherwise, you can create some kind of 'statistical' system, correlating the CPU ticks to the PC BIOS clock. The latter is way less precise, but constant.
With respect to Konrad Rudolph's answer, note that in my experience the frequency of the performance counter is around 3.7MHz, so sub-microsecond, but certainly not nanosecond precision. The actual frequency is hardware (and power-save mode) dependent. Nanosecond precision is somewhat unreasonable in any case since interrupt latencies and process/thread context switching times are far longer than that, and that is also the order of magnitude of individual machine instructions.
If you have a threaded application running on a multicore computer QueryPerformanceCounter
can (and will) return different values depending on which core the code is executing on. See this MSDN article. (rdtsc
has the same problem)
This is not just a theoretical problem; we ran into it with our application and had to conclude that the only reliable time source is timeGetTime
which only has ms precision (which fortunately was sufficient in our case). We also tried fixating the thread affinity for our threads to guarantee that each thread always got a consistent value from QueryPerformanceCounter
, this worked but it absolutely killed the performance in the application.
To sum things up there isn't a reliable timer on windows that kan be used to time thing with micro second precision (at least not when running on a multicore computer).
Here is a Timer class that will work both for Windows and Linux :
#ifndef INCLUDE_CTIMER_HPP_
#define INCLUDE_CTIMER_HPP_
#if defined(_MSC_VER)
# define NOMINMAX // workaround a bug in windows.h
# include <windows.h>
#else
# include <sys/time.h>
#endif
namespace Utils
{
class CTimer
{
private:
# if defined(_MSC_VER)
LARGE_INTEGER m_depart;
# else
timeval m_depart;
# endif
public:
inline void start()
{
# if defined(_MSC_VER)
QueryPerformanceCounter(&m_depart);
# else
gettimeofday(&m_depart, 0);
# endif
};
inline float GetSecondes() const
{
# if defined(_MSC_VER)
LARGE_INTEGER now;
LARGE_INTEGER freq;
QueryPerformanceCounter(&now);
QueryPerformanceFrequency(&freq);
return (now.QuadPart - m_depart.QuadPart) / static_cast<float>(freq.QuadPart);
# else
timeval now;
gettimeofday(&now, 0);
return now.tv_sec - m_depart.tv_sec + (now.tv_usec - m_depart.tv_usec) / 1000000.0f;
# endif
};
};
}
#endif // INCLUDE_CTIMER_HPP_
Thanks for the input...though I couldn't get nano, or microsecond resolution which would have been nice, I was however able to come up with this...maybe someone else will find it usefull.
class N_Script_Timer
{
public:
N_Script_Timer()
{
running = false;
milliseconds = 0;
seconds = 0;
start_t = 0;
end_t = 0;
}
void Start()
{
if(running)return;
running = true;
start_t = timeGetTime();
}
void End()
{
if(!running)return;
running = false;
end_t = timeGetTime();
milliseconds = end_t - start_t;
seconds = milliseconds / (float)1000;
}
float milliseconds;
float seconds;
private:
unsigned long start_t;
unsigned long end_t;
bool running;
};