Skip to content

Commit 9e0dd84

Browse files
committed
On Windows, use QueryPerformanceCounter instead of gettimeofday for
EXPLAIN ANALYZE instrumentation. Magnus Hagander
1 parent 354049c commit 9e0dd84

File tree

3 files changed

+72
-30
lines changed

3 files changed

+72
-30
lines changed

src/backend/commands/explain.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.129 2004/12/31 21:59:41 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.130 2005/03/20 22:27:51 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -46,7 +46,7 @@ typedef struct ExplainState
4646

4747
static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
4848
TupOutputState *tstate);
49-
static double elapsed_time(struct timeval * starttime);
49+
static double elapsed_time(instr_time * starttime);
5050
static void explain_outNode(StringInfo str,
5151
Plan *plan, PlanState *planstate,
5252
Plan *outer_plan,
@@ -212,12 +212,12 @@ void
212212
ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
213213
TupOutputState *tstate)
214214
{
215-
struct timeval starttime;
215+
instr_time starttime;
216216
double totaltime = 0;
217217
ExplainState *es;
218218
StringInfo str;
219219

220-
gettimeofday(&starttime, NULL);
220+
INSTR_TIME_SET_CURRENT(starttime);
221221

222222
/* If analyzing, we need to cope with queued triggers */
223223
if (stmt->analyze)
@@ -275,7 +275,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
275275
* Close down the query and free resources; also run any queued
276276
* AFTER triggers. Include time for this in the total runtime.
277277
*/
278-
gettimeofday(&starttime, NULL);
278+
INSTR_TIME_SET_CURRENT(starttime);
279279

280280
ExecutorEnd(queryDesc);
281281

@@ -303,23 +303,27 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
303303
pfree(es);
304304
}
305305

306-
/* Compute elapsed time in seconds since given gettimeofday() timestamp */
306+
/* Compute elapsed time in seconds since given timestamp */
307307
static double
308-
elapsed_time(struct timeval * starttime)
308+
elapsed_time(instr_time * starttime)
309309
{
310-
struct timeval endtime;
310+
instr_time endtime;
311311

312-
gettimeofday(&endtime, NULL);
312+
INSTR_TIME_SET_CURRENT(endtime);
313313

314+
#ifndef WIN32
314315
endtime.tv_sec -= starttime->tv_sec;
315316
endtime.tv_usec -= starttime->tv_usec;
316317
while (endtime.tv_usec < 0)
317318
{
318319
endtime.tv_usec += 1000000;
319320
endtime.tv_sec--;
320321
}
321-
return (double) endtime.tv_sec +
322-
(double) endtime.tv_usec / 1000000.0;
322+
#else /* WIN32 */
323+
endtime.QuadPart -= starttime->QuadPart;
324+
#endif
325+
326+
return INSTR_TIME_GET_DOUBLE(endtime);
323327
}
324328

325329
/*

src/backend/executor/instrument.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.9 2005/01/01 05:43:06 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.10 2005/03/20 22:27:51 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -36,29 +36,30 @@ InstrStartNode(Instrumentation *instr)
3636
if (!instr)
3737
return;
3838

39-
if (instr->starttime.tv_sec != 0 || instr->starttime.tv_usec != 0)
39+
if (!INSTR_TIME_IS_ZERO(instr->starttime))
4040
elog(DEBUG2, "InstrStartNode called twice in a row");
4141
else
42-
gettimeofday(&instr->starttime, NULL);
42+
INSTR_TIME_SET_CURRENT(instr->starttime);
4343
}
4444

4545
/* Exit from a plan node */
4646
void
4747
InstrStopNode(Instrumentation *instr, bool returnedTuple)
4848
{
49-
struct timeval endtime;
49+
instr_time endtime;
5050

5151
if (!instr)
5252
return;
5353

54-
if (instr->starttime.tv_sec == 0 && instr->starttime.tv_usec == 0)
54+
if (INSTR_TIME_IS_ZERO(instr->starttime))
5555
{
5656
elog(DEBUG2, "InstrStopNode without start");
5757
return;
5858
}
5959

60-
gettimeofday(&endtime, NULL);
60+
INSTR_TIME_SET_CURRENT(endtime);
6161

62+
#ifndef WIN32
6263
instr->counter.tv_sec += endtime.tv_sec - instr->starttime.tv_sec;
6364
instr->counter.tv_usec += endtime.tv_usec - instr->starttime.tv_usec;
6465

@@ -73,16 +74,17 @@ InstrStopNode(Instrumentation *instr, bool returnedTuple)
7374
instr->counter.tv_usec -= 1000000;
7475
instr->counter.tv_sec++;
7576
}
77+
#else /* WIN32 */
78+
instr->counter.QuadPart += (endtime.QuadPart - instr->starttime.QuadPart);
79+
#endif
7680

77-
instr->starttime.tv_sec = 0;
78-
instr->starttime.tv_usec = 0;
81+
INSTR_TIME_SET_ZERO(instr->starttime);
7982

8083
/* Is this the first tuple of this cycle? */
8184
if (!instr->running)
8285
{
8386
instr->running = true;
84-
instr->firsttuple = (double) instr->counter.tv_sec +
85-
(double) instr->counter.tv_usec / 1000000.0;
87+
instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
8688
}
8789

8890
if (returnedTuple)
@@ -103,8 +105,7 @@ InstrEndLoop(Instrumentation *instr)
103105
return;
104106

105107
/* Accumulate statistics */
106-
totaltime = (double) instr->counter.tv_sec +
107-
(double) instr->counter.tv_usec / 1000000.0;
108+
totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
108109

109110
instr->startup += instr->firsttuple;
110111
instr->total += totaltime;
@@ -113,10 +114,8 @@ InstrEndLoop(Instrumentation *instr)
113114

114115
/* Reset for next cycle (if any) */
115116
instr->running = false;
116-
instr->starttime.tv_sec = 0;
117-
instr->starttime.tv_usec = 0;
118-
instr->counter.tv_sec = 0;
119-
instr->counter.tv_usec = 0;
117+
INSTR_TIME_SET_ZERO(instr->starttime);
118+
INSTR_TIME_SET_ZERO(instr->counter);
120119
instr->firsttuple = 0;
121120
instr->tuplecount = 0;
122121
}

src/include/executor/instrument.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
88
*
9-
* $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.8 2005/01/01 05:43:09 momjian Exp $
9+
* $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.9 2005/03/20 22:27:52 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -16,12 +16,51 @@
1616
#include <sys/time.h>
1717

1818

19+
/*
20+
* gettimeofday() does not have sufficient resolution on Windows,
21+
* so we must use QueryPerformanceCounter() instead. These macros
22+
* also give some breathing room to use other high-precision-timing APIs
23+
* on yet other platforms. (The macro-ization is not complete, however;
24+
* see subtraction code in instrument.c and explain.c.)
25+
*/
26+
#ifndef WIN32
27+
28+
typedef struct timeval instr_time;
29+
30+
#define INSTR_TIME_IS_ZERO(t) ((t).tv_sec == 0 && (t).tv_usec == 0)
31+
#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
32+
#define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
33+
#define INSTR_TIME_GET_DOUBLE(t) \
34+
(((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
35+
36+
#else /* WIN32 */
37+
38+
typedef LARGE_INTEGER instr_time;
39+
40+
#define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
41+
#define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
42+
#define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
43+
#define INSTR_TIME_GET_DOUBLE(t) \
44+
(((double) (t).QuadPart) / GetTimerFrequency())
45+
46+
static __inline__ double
47+
GetTimerFrequency(void)
48+
{
49+
LARGE_INTEGER f;
50+
51+
QueryPerformanceFrequency(&f);
52+
return (double) f.QuadPart;
53+
}
54+
55+
#endif /* WIN32 */
56+
57+
1958
typedef struct Instrumentation
2059
{
2160
/* Info about current plan cycle: */
2261
bool running; /* TRUE if we've completed first tuple */
23-
struct timeval starttime; /* Start time of current iteration of node */
24-
struct timeval counter; /* Accumulates runtime for this node */
62+
instr_time starttime; /* Start time of current iteration of node */
63+
instr_time counter; /* Accumulates runtime for this node */
2564
double firsttuple; /* Time for first tuple of this cycle */
2665
double tuplecount; /* Tuples so far this cycle */
2766
/* Accumulated statistics across all completed cycles: */

0 commit comments

Comments
 (0)