#include // printf() #include // uint64_t #include // drand48() #include // select() #include // gettimeofday #include #include // rdtscll() //////////////////////////////////////////////////////////////////////////////// // Globals //////////////////////////////////////////////////////////////////////////////// enum { ITERATIONS = 1 << 22 }; static double seconds_per_tick; //////////////////////////////////////////////////////////////////////////////// // Prototypes //////////////////////////////////////////////////////////////////////////////// double gimme_timeofday(void); double get_time(void); void selectsleep(unsigned us); void init(void); //////////////////////////////////////////////////////////////////////////////// // Definitions //////////////////////////////////////////////////////////////////////////////// double gimme_timeofday(void) { struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec + 1e-6 * tv.tv_usec; } double get_time(void) { uint64_t t; rdtscll(t); return t * seconds_per_tick; } /** A good way to simply hang around doing nothing for awhile. */ void selectsleep(unsigned us) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = us; select(0,0,0,0,&tv); } /** Figure out how fast rdtscll() ticks. This should be equal to the frequency of the clock on the processor. Here's the bad news: I don't know if rdtscll() always uses the same processor so it may very well be necessary to set a processor affinity to get really good results over time. This piece of code by Mark Hahn from brain.mcmaster.ca/~hahn/. */ void init(void) { double sumx = 0; double sumy = 0; double sumxx = 0; double sumxy = 0; double slope; // least squares linear regression of ticks onto real time // as returned by gettimeofday. const unsigned n = 30; unsigned i; for ( unsigned int i = 0; i < n; ++i) { double breal,real,ticks; uint64_t aticks, bticks; breal = gimme_timeofday(); rdtscll(bticks); selectsleep((unsigned)(10000 + drand48() * 200000)); rdtscll(aticks); ticks = aticks - bticks; real = gimme_timeofday() - breal; sumx += real; sumxx += real * real; sumxy += real * ticks; sumy += ticks; } slope = ((sumxy - (sumx*sumy) / n) / (sumxx - (sumx*sumx) / n)); seconds_per_tick = 1.0 / slope; printf("Calibrated timer as %.6f Hz\n", slope); } int main(int argc, char *argv[]) { printf("Doing stuff\n"); #if 0 // Using rdtscll() printf("Using the cycle counter\n"); init(); double time_start = gimme_timeofday(); for (unsigned int i = 0; i < ITERATIONS; ++i) { double the_time; the_time = get_time(); } double time_end = gimme_timeofday(); #else // using gettimeofday() printf("Using gettimeofday\n"); double time_start = gimme_timeofday(); for (unsigned int i = 0; i < ITERATIONS; ++i) { double the_time; the_time = gimme_timeofday(); } double time_end = gimme_timeofday(); #endif double diff = time_end - time_start; double useconds = (diff / ITERATIONS) * 1e6; printf("%u iterations in %.3f seconds is %.3f useconds per iteration.\n", ITERATIONS, diff, useconds); printf("Done\n"); return 0; }