PostgreSQL Source Code  git master
instr_time.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * instr_time.h
4  * portable high-precision interval timing
5  *
6  * This file provides an abstraction layer to hide portability issues in
7  * interval timing. On Unix we use clock_gettime() if available, else
8  * gettimeofday(). On Windows, gettimeofday() gives a low-precision result
9  * so we must use QueryPerformanceCounter() instead. These macros also give
10  * some breathing room to use other high-precision-timing APIs.
11  *
12  * The basic data type is instr_time, which all callers should treat as an
13  * opaque typedef. instr_time can store either an absolute time (of
14  * unspecified reference time) or an interval. The operations provided
15  * for it are:
16  *
17  * INSTR_TIME_IS_ZERO(t) is t equal to zero?
18  *
19  * INSTR_TIME_SET_ZERO(t) set t to zero (memset is acceptable too)
20  *
21  * INSTR_TIME_SET_CURRENT(t) set t to current time
22  *
23  * INSTR_TIME_ADD(x, y) x += y
24  *
25  * INSTR_TIME_SUBTRACT(x, y) x -= y
26  *
27  * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z)
28  *
29  * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds)
30  *
31  * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds)
32  *
33  * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds)
34  *
35  * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
36  * absolute times to intervals. The INSTR_TIME_GET_xxx operations are
37  * only useful on intervals.
38  *
39  * When summing multiple measurements, it's recommended to leave the
40  * running sum in instr_time form (ie, use INSTR_TIME_ADD or
41  * INSTR_TIME_ACCUM_DIFF) and convert to a result format only at the end.
42  *
43  * Beware of multiple evaluations of the macro arguments.
44  *
45  *
46  * Copyright (c) 2001-2017, PostgreSQL Global Development Group
47  *
48  * src/include/portability/instr_time.h
49  *
50  *-------------------------------------------------------------------------
51  */
52 #ifndef INSTR_TIME_H
53 #define INSTR_TIME_H
54 
55 #ifndef WIN32
56 
57 #ifdef HAVE_CLOCK_GETTIME
58 
59 /* Use clock_gettime() */
60 
61 #include <time.h>
62 
63 /*
64  * The best clockid to use according to the POSIX spec is CLOCK_MONOTONIC,
65  * since that will give reliable interval timing even in the face of changes
66  * to the system clock. However, POSIX doesn't require implementations to
67  * provide anything except CLOCK_REALTIME, so fall back to that if we don't
68  * find CLOCK_MONOTONIC.
69  *
70  * Also, some implementations have nonstandard clockids with better properties
71  * than CLOCK_MONOTONIC. In particular, as of macOS 10.12, Apple provides
72  * CLOCK_MONOTONIC_RAW which is both faster to read and higher resolution than
73  * their version of CLOCK_MONOTONIC.
74  */
75 #if defined(__darwin__) && defined(CLOCK_MONOTONIC_RAW)
76 #define PG_INSTR_CLOCK CLOCK_MONOTONIC_RAW
77 #elif defined(CLOCK_MONOTONIC)
78 #define PG_INSTR_CLOCK CLOCK_MONOTONIC
79 #else
80 #define PG_INSTR_CLOCK CLOCK_REALTIME
81 #endif
82 
83 typedef struct timespec instr_time;
84 
85 #define INSTR_TIME_IS_ZERO(t) ((t).tv_nsec == 0 && (t).tv_sec == 0)
86 
87 #define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_nsec = 0)
88 
89 #define INSTR_TIME_SET_CURRENT(t) ((void) clock_gettime(PG_INSTR_CLOCK, &(t)))
90 
91 #define INSTR_TIME_ADD(x,y) \
92  do { \
93  (x).tv_sec += (y).tv_sec; \
94  (x).tv_nsec += (y).tv_nsec; \
95  /* Normalize */ \
96  while ((x).tv_nsec >= 1000000000) \
97  { \
98  (x).tv_nsec -= 1000000000; \
99  (x).tv_sec++; \
100  } \
101  } while (0)
102 
103 #define INSTR_TIME_SUBTRACT(x,y) \
104  do { \
105  (x).tv_sec -= (y).tv_sec; \
106  (x).tv_nsec -= (y).tv_nsec; \
107  /* Normalize */ \
108  while ((x).tv_nsec < 0) \
109  { \
110  (x).tv_nsec += 1000000000; \
111  (x).tv_sec--; \
112  } \
113  } while (0)
114 
115 #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
116  do { \
117  (x).tv_sec += (y).tv_sec - (z).tv_sec; \
118  (x).tv_nsec += (y).tv_nsec - (z).tv_nsec; \
119  /* Normalize after each add to avoid overflow/underflow of tv_nsec */ \
120  while ((x).tv_nsec < 0) \
121  { \
122  (x).tv_nsec += 1000000000; \
123  (x).tv_sec--; \
124  } \
125  while ((x).tv_nsec >= 1000000000) \
126  { \
127  (x).tv_nsec -= 1000000000; \
128  (x).tv_sec++; \
129  } \
130  } while (0)
131 
132 #define INSTR_TIME_GET_DOUBLE(t) \
133  (((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
134 
135 #define INSTR_TIME_GET_MILLISEC(t) \
136  (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
137 
138 #define INSTR_TIME_GET_MICROSEC(t) \
139  (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
140 
141 #else /* !HAVE_CLOCK_GETTIME */
142 
143 /* Use gettimeofday() */
144 
145 #include <sys/time.h>
146 
147 typedef struct timeval instr_time;
148 
149 #define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0)
150 
151 #define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
152 
153 #define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
154 
155 #define INSTR_TIME_ADD(x,y) \
156  do { \
157  (x).tv_sec += (y).tv_sec; \
158  (x).tv_usec += (y).tv_usec; \
159  /* Normalize */ \
160  while ((x).tv_usec >= 1000000) \
161  { \
162  (x).tv_usec -= 1000000; \
163  (x).tv_sec++; \
164  } \
165  } while (0)
166 
167 #define INSTR_TIME_SUBTRACT(x,y) \
168  do { \
169  (x).tv_sec -= (y).tv_sec; \
170  (x).tv_usec -= (y).tv_usec; \
171  /* Normalize */ \
172  while ((x).tv_usec < 0) \
173  { \
174  (x).tv_usec += 1000000; \
175  (x).tv_sec--; \
176  } \
177  } while (0)
178 
179 #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
180  do { \
181  (x).tv_sec += (y).tv_sec - (z).tv_sec; \
182  (x).tv_usec += (y).tv_usec - (z).tv_usec; \
183  /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
184  while ((x).tv_usec < 0) \
185  { \
186  (x).tv_usec += 1000000; \
187  (x).tv_sec--; \
188  } \
189  while ((x).tv_usec >= 1000000) \
190  { \
191  (x).tv_usec -= 1000000; \
192  (x).tv_sec++; \
193  } \
194  } while (0)
195 
196 #define INSTR_TIME_GET_DOUBLE(t) \
197  (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
198 
199 #define INSTR_TIME_GET_MILLISEC(t) \
200  (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
201 
202 #define INSTR_TIME_GET_MICROSEC(t) \
203  (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
204 
205 #endif /* HAVE_CLOCK_GETTIME */
206 
207 #else /* WIN32 */
208 
209 /* Use QueryPerformanceCounter() */
210 
211 typedef LARGE_INTEGER instr_time;
212 
213 #define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
214 
215 #define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
216 
217 #define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
218 
219 #define INSTR_TIME_ADD(x,y) \
220  ((x).QuadPart += (y).QuadPart)
221 
222 #define INSTR_TIME_SUBTRACT(x,y) \
223  ((x).QuadPart -= (y).QuadPart)
224 
225 #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
226  ((x).QuadPart += (y).QuadPart - (z).QuadPart)
227 
228 #define INSTR_TIME_GET_DOUBLE(t) \
229  (((double) (t).QuadPart) / GetTimerFrequency())
230 
231 #define INSTR_TIME_GET_MILLISEC(t) \
232  (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
233 
234 #define INSTR_TIME_GET_MICROSEC(t) \
235  ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
236 
237 static inline double
238 GetTimerFrequency(void)
239 {
240  LARGE_INTEGER f;
241 
242  QueryPerformanceFrequency(&f);
243  return (double) f.QuadPart;
244 }
245 
246 #endif /* WIN32 */
247 
248 #endif /* INSTR_TIME_H */
struct timeval instr_time
Definition: instr_time.h:147