Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit03023a2

Browse files
committed
instr_time: Represent time as an int64 on all platforms
Until now we used struct timespec for instr_time on all platforms butwindows. Using struct timespec causes a fair bit of memory (struct timeval is16 bytes) and runtime overhead (much more complicated additions). Instead wecan convert the time to nanoseconds in INSTR_TIME_SET_CURRENT(), making theremaining operations cheaper.Representing time as int64 nanoseconds provides sufficient range, ~292 yearsrelative to a starting point (depending on clock source, relative to the unixepoch or the system's boot time). That'd not be sufficient for calendar timestored on disk, but is plenty for runtime interval time measurement.On windows instr_time already is represented as cycles. It might make sense torepresent time as cycles on other platforms as well, as using cycleacquisition instructions like rdtsc directly can reduce the overhead of timeacquisition substantially. This could be done in a fairly localized manner asthe code stands after this commit.Because the windows and non-windows paths are now more similar, use a commonset of macros. To make that possible, most of the use of LARGE_INTEGER had tobe removed, which looks nicer anyway.To avoid users of the API relying on the integer representation, we wrap the64bit integer inside struct struct instr_time.Author: Andres Freund <andres@anarazel.de>Author: Lukas Fittl <lukas@fittl.com>Author: David Geier <geidav.pg@gmail.com>Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>Discussion:https://postgr.es/m/20230113195547.k4nlrmawpijqwlsa@awork3.anarazel.de
1 parent25b2aba commit03023a2

File tree

1 file changed

+86
-76
lines changed

1 file changed

+86
-76
lines changed

‎src/include/portability/instr_time.h

Lines changed: 86 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
*
3535
* INSTR_TIME_GET_MICROSEC(t)convert t to uint64 (in microseconds)
3636
*
37+
* INSTR_TIME_GET_NANOSEC(t)convert t to uint64 (in nanoseconds)
38+
*
3739
* Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
3840
* absolute times to intervals. The INSTR_TIME_GET_xxx operations are
3941
* only useful on intervals.
@@ -54,8 +56,32 @@
5456
#ifndefINSTR_TIME_H
5557
#defineINSTR_TIME_H
5658

59+
60+
/*
61+
* We store interval times as an int64 integer on all platforms, as int64 is
62+
* cheap to add/subtract, the most common operation for instr_time. The
63+
* acquisition of time and converting to specific units of time is platform
64+
* specific.
65+
*
66+
* To avoid users of the API relying on the integer representation, we wrap
67+
* the 64bit integer in a struct.
68+
*/
69+
typedefstructinstr_time
70+
{
71+
int64ticks;/* in platforms specific unit */
72+
}instr_time;
73+
74+
75+
/* helpers macros used in platform specific code below */
76+
77+
#defineNS_PER_SINT64CONST(1000000000)
78+
#defineNS_PER_MSINT64CONST(1000000)
79+
#defineNS_PER_USINT64CONST(1000)
80+
81+
5782
#ifndefWIN32
5883

84+
5985
/* Use clock_gettime() */
6086

6187
#include<time.h>
@@ -80,93 +106,43 @@
80106
#definePG_INSTR_CLOCKCLOCK_REALTIME
81107
#endif
82108

83-
typedefstructtimespecinstr_time;
84-
85-
#defineINSTR_TIME_IS_ZERO(t)((t).tv_nsec == 0 && (t).tv_sec == 0)
86-
87-
#defineINSTR_TIME_SET_ZERO(t)((t).tv_sec = 0, (t).tv_nsec = 0)
88-
89-
#defineINSTR_TIME_SET_CURRENT(t)((void) clock_gettime(PG_INSTR_CLOCK, &(t)))
90-
91-
#defineINSTR_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)
109+
/* helper for INSTR_TIME_SET_CURRENT */
110+
staticinlineinstr_time
111+
pg_clock_gettime_ns(void)
112+
{
113+
instr_timenow;
114+
structtimespectmp;
102115

103-
#defineINSTR_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)
116+
clock_gettime(PG_INSTR_CLOCK,&tmp);
117+
now.ticks=tmp.tv_sec*NS_PER_S+tmp.tv_nsec;
114118

115-
#defineINSTR_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)
119+
returnnow;
120+
}
131121

132-
#defineINSTR_TIME_GET_DOUBLE(t) \
133-
(((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
122+
#defineINSTR_TIME_SET_CURRENT(t) \
123+
((t) = pg_clock_gettime_ns())
134124

135-
#defineINSTR_TIME_GET_MILLISEC(t) \
136-
(((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
125+
#defineINSTR_TIME_GET_NANOSEC(t) \
126+
((int64) (t).ticks)
137127

138-
#defineINSTR_TIME_GET_MICROSEC(t) \
139-
(((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
140128

141129
#else/* WIN32 */
142130

143-
/* Use QueryPerformanceCounter() */
144-
145-
typedefLARGE_INTEGERinstr_time;
146-
147-
#defineINSTR_TIME_IS_ZERO(t)((t).QuadPart == 0)
148-
149-
#defineINSTR_TIME_SET_ZERO(t)((t).QuadPart = 0)
150-
151-
#defineINSTR_TIME_SET_CURRENT(t)QueryPerformanceCounter(&(t))
152-
153-
#defineINSTR_TIME_ADD(x,y) \
154-
((x).QuadPart += (y).QuadPart)
155-
156-
#defineINSTR_TIME_SUBTRACT(x,y) \
157-
((x).QuadPart -= (y).QuadPart)
158131

159-
#defineINSTR_TIME_ACCUM_DIFF(x,y,z) \
160-
((x).QuadPart += (y).QuadPart - (z).QuadPart)
132+
/* Use QueryPerformanceCounter() */
161133

162-
#defineINSTR_TIME_GET_DOUBLE(t) \
163-
(((double) (t).QuadPart) / GetTimerFrequency())
134+
/* helper for INSTR_TIME_SET_CURRENT */
135+
staticinlineinstr_time
136+
pg_query_performance_counter(void)
137+
{
138+
instr_timenow;
139+
LARGE_INTEGERtmp;
164140

165-
#defineINSTR_TIME_GET_MILLISEC(t) \
166-
(((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
141+
QueryPerformanceCounter(&tmp);
142+
now.ticks=tmp.QuadPart;
167143

168-
#defineINSTR_TIME_GET_MICROSEC(t) \
169-
((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
144+
returnnow;
145+
}
170146

171147
staticinlinedouble
172148
GetTimerFrequency(void)
@@ -177,11 +153,45 @@ GetTimerFrequency(void)
177153
return (double)f.QuadPart;
178154
}
179155

156+
#defineINSTR_TIME_SET_CURRENT(t) \
157+
((t) = pg_query_performance_counter())
158+
159+
#defineINSTR_TIME_GET_NANOSEC(t) \
160+
((int64) ((t).ticks * ((double) NS_PER_S / GetTimerFrequency())))
161+
180162
#endif/* WIN32 */
181163

182-
/* same macro on all platforms */
164+
165+
/*
166+
* Common macros
167+
*/
168+
169+
#defineINSTR_TIME_IS_ZERO(t)((t).ticks == 0)
170+
171+
172+
#defineINSTR_TIME_SET_ZERO(t)((t).ticks = 0)
183173

184174
#defineINSTR_TIME_SET_CURRENT_LAZY(t) \
185175
(INSTR_TIME_IS_ZERO(t) ? INSTR_TIME_SET_CURRENT(t), true : false)
186176

177+
178+
#defineINSTR_TIME_ADD(x,y) \
179+
((x).ticks += (y).ticks)
180+
181+
#defineINSTR_TIME_SUBTRACT(x,y) \
182+
((x).ticks -= (y).ticks)
183+
184+
#defineINSTR_TIME_ACCUM_DIFF(x,y,z) \
185+
((x).ticks += (y).ticks - (z).ticks)
186+
187+
188+
#defineINSTR_TIME_GET_DOUBLE(t) \
189+
((double) INSTR_TIME_GET_NANOSEC(t) / NS_PER_S)
190+
191+
#defineINSTR_TIME_GET_MILLISEC(t) \
192+
((double) INSTR_TIME_GET_NANOSEC(t) / NS_PER_MS)
193+
194+
#defineINSTR_TIME_GET_MICROSEC(t) \
195+
(INSTR_TIME_GET_NANOSEC(t) / NS_PER_US)
196+
187197
#endif/* INSTR_TIME_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp