Header And Logo

PostgreSQL
| The world's most advanced open source database.

instr_time.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * instr_time.h
00004  *    portable high-precision interval timing
00005  *
00006  * This file provides an abstraction layer to hide portability issues in
00007  * interval timing.  On Unix we use gettimeofday(), but on Windows that
00008  * gives a low-precision result so we must use QueryPerformanceCounter()
00009  * instead.  These macros also give some breathing room to use other
00010  * high-precision-timing APIs on yet other platforms.
00011  *
00012  * The basic data type is instr_time, which all callers should treat as an
00013  * opaque typedef.  instr_time can store either an absolute time (of
00014  * unspecified reference time) or an interval.  The operations provided
00015  * for it are:
00016  *
00017  * INSTR_TIME_IS_ZERO(t)            is t equal to zero?
00018  *
00019  * INSTR_TIME_SET_ZERO(t)           set t to zero (memset is acceptable too)
00020  *
00021  * INSTR_TIME_SET_CURRENT(t)        set t to current time
00022  *
00023  * INSTR_TIME_ADD(x, y)             x += y
00024  *
00025  * INSTR_TIME_SUBTRACT(x, y)        x -= y
00026  *
00027  * INSTR_TIME_ACCUM_DIFF(x, y, z)   x += (y - z)
00028  *
00029  * INSTR_TIME_GET_DOUBLE(t)         convert t to double (in seconds)
00030  *
00031  * INSTR_TIME_GET_MILLISEC(t)       convert t to double (in milliseconds)
00032  *
00033  * INSTR_TIME_GET_MICROSEC(t)       convert t to uint64 (in microseconds)
00034  *
00035  * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
00036  * absolute times to intervals.  The INSTR_TIME_GET_xxx operations are
00037  * only useful on intervals.
00038  *
00039  * When summing multiple measurements, it's recommended to leave the
00040  * running sum in instr_time form (ie, use INSTR_TIME_ADD or
00041  * INSTR_TIME_ACCUM_DIFF) and convert to a result format only at the end.
00042  *
00043  * Beware of multiple evaluations of the macro arguments.
00044  *
00045  *
00046  * Copyright (c) 2001-2013, PostgreSQL Global Development Group
00047  *
00048  * src/include/portability/instr_time.h
00049  *
00050  *-------------------------------------------------------------------------
00051  */
00052 #ifndef INSTR_TIME_H
00053 #define INSTR_TIME_H
00054 
00055 #ifndef WIN32
00056 
00057 #include <sys/time.h>
00058 
00059 typedef struct timeval instr_time;
00060 
00061 #define INSTR_TIME_IS_ZERO(t)   ((t).tv_usec == 0 && (t).tv_sec == 0)
00062 
00063 #define INSTR_TIME_SET_ZERO(t)  ((t).tv_sec = 0, (t).tv_usec = 0)
00064 
00065 #define INSTR_TIME_SET_CURRENT(t)   gettimeofday(&(t), NULL)
00066 
00067 #define INSTR_TIME_ADD(x,y) \
00068     do { \
00069         (x).tv_sec += (y).tv_sec; \
00070         (x).tv_usec += (y).tv_usec; \
00071         /* Normalize */ \
00072         while ((x).tv_usec >= 1000000) \
00073         { \
00074             (x).tv_usec -= 1000000; \
00075             (x).tv_sec++; \
00076         } \
00077     } while (0)
00078 
00079 #define INSTR_TIME_SUBTRACT(x,y) \
00080     do { \
00081         (x).tv_sec -= (y).tv_sec; \
00082         (x).tv_usec -= (y).tv_usec; \
00083         /* Normalize */ \
00084         while ((x).tv_usec < 0) \
00085         { \
00086             (x).tv_usec += 1000000; \
00087             (x).tv_sec--; \
00088         } \
00089     } while (0)
00090 
00091 #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
00092     do { \
00093         (x).tv_sec += (y).tv_sec - (z).tv_sec; \
00094         (x).tv_usec += (y).tv_usec - (z).tv_usec; \
00095         /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
00096         while ((x).tv_usec < 0) \
00097         { \
00098             (x).tv_usec += 1000000; \
00099             (x).tv_sec--; \
00100         } \
00101         while ((x).tv_usec >= 1000000) \
00102         { \
00103             (x).tv_usec -= 1000000; \
00104             (x).tv_sec++; \
00105         } \
00106     } while (0)
00107 
00108 #define INSTR_TIME_GET_DOUBLE(t) \
00109     (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
00110 
00111 #define INSTR_TIME_GET_MILLISEC(t) \
00112     (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
00113 
00114 #define INSTR_TIME_GET_MICROSEC(t) \
00115     (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
00116 #else                           /* WIN32 */
00117 
00118 typedef LARGE_INTEGER instr_time;
00119 
00120 #define INSTR_TIME_IS_ZERO(t)   ((t).QuadPart == 0)
00121 
00122 #define INSTR_TIME_SET_ZERO(t)  ((t).QuadPart = 0)
00123 
00124 #define INSTR_TIME_SET_CURRENT(t)   QueryPerformanceCounter(&(t))
00125 
00126 #define INSTR_TIME_ADD(x,y) \
00127     ((x).QuadPart += (y).QuadPart)
00128 
00129 #define INSTR_TIME_SUBTRACT(x,y) \
00130     ((x).QuadPart -= (y).QuadPart)
00131 
00132 #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
00133     ((x).QuadPart += (y).QuadPart - (z).QuadPart)
00134 
00135 #define INSTR_TIME_GET_DOUBLE(t) \
00136     (((double) (t).QuadPart) / GetTimerFrequency())
00137 
00138 #define INSTR_TIME_GET_MILLISEC(t) \
00139     (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
00140 
00141 #define INSTR_TIME_GET_MICROSEC(t) \
00142     ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
00143 
00144 static inline double
00145 GetTimerFrequency(void)
00146 {
00147     LARGE_INTEGER f;
00148 
00149     QueryPerformanceFrequency(&f);
00150     return (double) f.QuadPart;
00151 }
00152 #endif   /* WIN32 */
00153 
00154 #endif   /* INSTR_TIME_H */