What is the fastest timing system a C/C++ programmer can use?
For example:
time() will give the seconds since Jan 01 1970 00:00.
GetTickCount() on Windows will give the time, in milliseconds, since the system's start-up time, but is limited to 49.7 days (after that it simply wraps back to zero).
I want to get the current time, or ticks since system/app start-up time, in milliseconds.
The biggest concern is the method's overhead - I need the lightest one, because I'm about to call it many many times per second.
My case is that I have a worker thread, and to that worker thread I post pending jobs. Each job has an "execution time". So, I don't care if the time is the current "real" time or the time since the system's uptime - it just must be linear and light.
Edit:
unsigned __int64 GetTickCountEx()
{
static DWORD dwWraps = 0;
static DWORD dwLast = 0;
DWORD dwCurrent = 0;
timeMutex.lock();
dwCurrent = GetTickCount();
if(dwLast > dwCurrent)
dwWraps++;
dwLast = dwCurrent;
unsigned __int64 timeResult = ((unsigned __int64)0xFFFFFFFF * dwWraps) + dwCurrent;
timeMutex.unlock();
return timeResult;
}
For timing, the current Microsoft recommendation is to use QueryPerformanceCounter
& QueryPerformanceFrequency
.
This will give you better-than-millisecond timing. If the system doesn't support a high-resolution timer, then it will default to milliseconds (the same as GetTickCount
).
Here is a short Microsoft article with examples of why you should use it :)
I recently had this question and did some research. The good news is that all three of the major operating systems provide some sort of high resolution timer. The bad news is that it is a different API call on each system. For POSIX operating systems you want to use clock_gettime(). If you're on Mac OS X, however, this is not supported, you have to use mach_get_time(). For windows, use QueryPerformanceCounter. Alternatively, with compilers that support OpenMP, you can use omp_get_wtime(), but it may not provide the resolution that you are looking for.
I also found cycle.h from fftw.org (www.fftw.org/cycle.h) to be useful.
Here is some code that calls a timer on each OS, using some ugly #ifdef statements. The usage is very simple: Timer t; t.tic(); SomeOperation(); t.toc("Message"); And it will print out the elapsed time in seconds.
#ifndef TIMER_H
#define TIMER_H
#include <iostream>
#include <string>
#include <vector>
# if (defined(__MACH__) && defined(__APPLE__))
# define _MAC
# elif (defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(_WIN64))
# define _WINDOWS
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
#endif
# if defined(_MAC)
# include <mach/mach_time.h>
# elif defined(_WINDOWS)
# include <windows.h>
# else
# include <time.h>
# endif
#if defined(_MAC)
typedef uint64_t timer_t;
typedef double timer_c;
#elif defined(_WINDOWS)
typedef LONGLONG timer_t;
typedef LARGE_INTEGER timer_c;
#else
typedef double timer_t;
typedef timespec timer_c;
#endif
//==============================================================================
// Timer
// A quick class to do benchmarking.
// Example: Timer t; t.tic(); SomeSlowOp(); t.toc("Some Message");
class Timer {
public:
Timer();
inline void tic();
inline void toc();
inline void toc(const std::string &msg);
void print(const std::string &msg);
void print();
void reset();
double getTime();
private:
timer_t start;
double duration;
timer_c ts;
double conv_factor;
double elapsed_time;
};
Timer::Timer() {
#if defined(_MAC)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
conv_factor = (static_cast<double>(info.numer))/
(static_cast<double>(info.denom));
conv_factor = conv_factor*1.0e-9;
#elif defined(_WINDOWS)
timer_c freq;
QueryPerformanceFrequency(&freq);
conv_factor = 1.0/(static_cast<double>freq.QuadPart);
#else
conv_factor = 1.0;
#endif
reset();
}
inline void Timer::tic() {
#if defined(_MAC)
start = mach_absolute_time();
#elif defined(_WINDOWS)
QueryPerformanceCounter(&ts);
start = ts.QuadPart;
#else
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
start = static_cast<double>(ts.tv_sec) + 1.0e-9 *
static_cast<double>(ts.tv_nsec);
#endif
}
inline void Timer::toc() {
#if defined(_MAC)
duration = static_cast<double>(mach_absolute_time() - start);
#elif defined(_WINDOWS)
QueryPerformanceCounter(&qpc_t);
duration = static_cast<double>(qpc_t.QuadPart - start);
#else
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
duration = (static_cast<double>(ts.tv_sec) + 1.0e-9 *
static_cast<double>(ts.tv_nsec)) - start;
#endif
elapsed_time = duration*conv_factor;
}
inline void Timer::toc(const std::string &msg) { toc(); print(msg); };
void Timer::print(const std::string &msg) {
std::cout << msg << " "; print();
}
void Timer::print() {
if(elapsed_time) {
std::cout << "elapsed time: " << elapsed_time << " seconds\n";
}
}
void Timer::reset() { start = 0; duration = 0; elapsed_time = 0; }
double Timer::getTime() { return elapsed_time; }
#if defined(_WINDOWS)
# undef WIN32_LEAN_AND_MEAN
#endif
#endif // TIMER_H
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With