// Compile with "g++ -o time time.c -lrt"
#include <time.h> // for gettimeofday, CLOCK_PROCESS_CPUTIME_ID, clock_gettime 
#include <sys/time.h> 
#include <stdio.h> 

typedef unsigned long long uint64_t;
typedef unsigned int       uint32_t;

static inline uint64_t hrtime()
{
    uint32_t high, low;
    __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
    uint64_t x = high; x <<= 32; x |= low;
    return x;
}

int main(int argc, char**argv) 
{ 
  int i;
  struct timeval tv1, tv2; 
   
  clock_t t2, t1 = clock();

  do { 
      t2 = clock();
  } while (t2 == t1);

  printf("clock resolution: %.3f s\n", (double)((t2 - t1)) / CLOCKS_PER_SEC);

  gettimeofday(&tv1, NULL); 
  do { 
      gettimeofday(&tv2, NULL); 
  } while (tv1.tv_usec == tv2.tv_usec); 


  printf("gettimeofday() resolution: %d us\n", tv2.tv_usec - tv1.tv_usec + 
         1000000 * (tv2.tv_sec - tv1.tv_sec)); 

  uint64_t ut2, ut1 = hrtime();

  for(i=0; i < 10000; i++)
    gettimeofday(&tv1, NULL);
  ut2 = hrtime();

  printf("gettimeofday() duration = %d us\n", (ut2 - ut1) / (1000 * 10000));
  
  ut1 = hrtime(); 
  do { 
      ut2 = hrtime(); 
  } while (ut1 == ut2); 

  printf("hrtime() resolution: %d ns\n", ut2 - ut1); 

  ut1 = hrtime();
  for(i=0; i < 1000000; i++)
    ut2 = hrtime();

  printf("hrtime() 1 iteration cost = %d ns\n", (ut2 - ut1) / 1000000);

  // High resolution timer
  {
    uint64_t t;
    struct timespec tp, tp1;

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);

    do {
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp1);
    } while (tp.tv_nsec == tp1.tv_nsec);

    printf("clock_gettime() resolution = %d ns\n", tp1.tv_nsec - tp.tv_nsec);

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
    for(i=0; i < 1000000; i++)
      clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp1);
    
    printf("clock_gettime() 1 iteration cost = %d ns\n", (tp1.tv_nsec - tp.tv_nsec + (tp1.tv_sec - tp.tv_sec)*1000000000) / 1000000);
  }
  
  return 0; 
} 


