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