diff options
Diffstat (limited to 'src/include/portability/instr_time.h')
-rw-r--r-- | src/include/portability/instr_time.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h new file mode 100644 index 00000000000..666d495f203 --- /dev/null +++ b/src/include/portability/instr_time.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------- + * + * instr_time.h + * portable high-precision interval timing + * + * This file provides an abstraction layer to hide portability issues in + * interval timing. On Unix we use gettimeofday(), but on Windows that + * gives a low-precision result so we must use QueryPerformanceCounter() + * instead. These macros also give some breathing room to use other + * high-precision-timing APIs on yet other platforms. + * + * The basic data type is instr_time, which all callers should treat as an + * opaque typedef. instr_time can store either an absolute time (of + * unspecified reference time) or an interval. The operations provided + * for it are: + * + * INSTR_TIME_IS_ZERO(t) is t equal to zero? + * + * INSTR_TIME_SET_ZERO(t) set t to zero (memset is acceptable too) + * + * INSTR_TIME_SET_CURRENT(t) set t to current time + * + * INSTR_TIME_SUBTRACT(x, y) x -= y + * + * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z) + * + * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds) + * + * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds) + * + * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds) + * + * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert + * absolute times to intervals. The INSTR_TIME_GET_xxx operations are + * only useful on intervals. + * + * When summing multiple measurements, it's recommended to leave the + * running sum in instr_time form (ie, use INSTR_TIME_ACCUM_DIFF) and + * convert to a result format only at the end. + * + * Beware of multiple evaluations of the macro arguments. + * + * + * Copyright (c) 2001-2008, PostgreSQL Global Development Group + * + * $PostgreSQL: pgsql/src/include/portability/instr_time.h,v 1.1 2008/05/14 19:10:29 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef INSTR_TIME_H +#define INSTR_TIME_H + +#ifndef WIN32 + +#include <sys/time.h> + +typedef struct timeval instr_time; + +#define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0) + +#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0) + +#define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL) + +#define INSTR_TIME_SUBTRACT(x,y) \ + do { \ + (x).tv_sec -= (y).tv_sec; \ + (x).tv_usec -= (y).tv_usec; \ + /* Normalize */ \ + while ((x).tv_usec < 0) \ + { \ + (x).tv_usec += 1000000; \ + (x).tv_sec--; \ + } \ + } while (0) + +#define INSTR_TIME_ACCUM_DIFF(x,y,z) \ + do { \ + (x).tv_sec += (y).tv_sec - (z).tv_sec; \ + (x).tv_usec += (y).tv_usec - (z).tv_usec; \ + /* Normalize after each add to avoid overflow/underflow of tv_usec */ \ + while ((x).tv_usec < 0) \ + { \ + (x).tv_usec += 1000000; \ + (x).tv_sec--; \ + } \ + while ((x).tv_usec >= 1000000) \ + { \ + (x).tv_usec -= 1000000; \ + (x).tv_sec++; \ + } \ + } while (0) + +#define INSTR_TIME_GET_DOUBLE(t) \ + (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0) + +#define INSTR_TIME_GET_MILLISEC(t) \ + (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0) + +#define INSTR_TIME_GET_MICROSEC(t) \ + (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec) + +#else /* WIN32 */ + +typedef LARGE_INTEGER instr_time; + +#define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0) + +#define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0) + +#define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t)) + +#define INSTR_TIME_SUBTRACT(x,y) \ + ((x).QuadPart -= (y).QuadPart) + +#define INSTR_TIME_ACCUM_DIFF(x,y,z) \ + ((x).QuadPart += (y).QuadPart - (z).QuadPart) + +#define INSTR_TIME_GET_DOUBLE(t) \ + (((double) (t).QuadPart) / GetTimerFrequency()) + +#define INSTR_TIME_GET_MILLISEC(t) \ + (((double) (t).QuadPart * 1000.0) / GetTimerFrequency()) + +#define INSTR_TIME_GET_MICROSEC(t) \ + ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency())) + +static __inline__ double +GetTimerFrequency(void) +{ + LARGE_INTEGER f; + + QueryPerformanceFrequency(&f); + return (double) f.QuadPart; +} + +#endif /* WIN32 */ + +#endif /* INSTR_TIME_H */ |