* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.129 2004/12/31 21:59:41 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.130 2005/03/20 22:27:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
TupOutputState *tstate);
-static double elapsed_time(struct timeval * starttime);
+static double elapsed_time(instr_time * starttime);
static void explain_outNode(StringInfo str,
Plan *plan, PlanState *planstate,
Plan *outer_plan,
ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
TupOutputState *tstate)
{
- struct timeval starttime;
+ instr_time starttime;
double totaltime = 0;
ExplainState *es;
StringInfo str;
- gettimeofday(&starttime, NULL);
+ INSTR_TIME_SET_CURRENT(starttime);
/* If analyzing, we need to cope with queued triggers */
if (stmt->analyze)
* Close down the query and free resources; also run any queued
* AFTER triggers. Include time for this in the total runtime.
*/
- gettimeofday(&starttime, NULL);
+ INSTR_TIME_SET_CURRENT(starttime);
ExecutorEnd(queryDesc);
pfree(es);
}
-/* Compute elapsed time in seconds since given gettimeofday() timestamp */
+/* Compute elapsed time in seconds since given timestamp */
static double
-elapsed_time(struct timeval * starttime)
+elapsed_time(instr_time * starttime)
{
- struct timeval endtime;
+ instr_time endtime;
- gettimeofday(&endtime, NULL);
+ INSTR_TIME_SET_CURRENT(endtime);
+#ifndef WIN32
endtime.tv_sec -= starttime->tv_sec;
endtime.tv_usec -= starttime->tv_usec;
while (endtime.tv_usec < 0)
endtime.tv_usec += 1000000;
endtime.tv_sec--;
}
- return (double) endtime.tv_sec +
- (double) endtime.tv_usec / 1000000.0;
+#else /* WIN32 */
+ endtime.QuadPart -= starttime->QuadPart;
+#endif
+
+ return INSTR_TIME_GET_DOUBLE(endtime);
}
/*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.9 2005/01/01 05:43:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.10 2005/03/20 22:27:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (!instr)
return;
- if (instr->starttime.tv_sec != 0 || instr->starttime.tv_usec != 0)
+ if (!INSTR_TIME_IS_ZERO(instr->starttime))
elog(DEBUG2, "InstrStartNode called twice in a row");
else
- gettimeofday(&instr->starttime, NULL);
+ INSTR_TIME_SET_CURRENT(instr->starttime);
}
/* Exit from a plan node */
void
InstrStopNode(Instrumentation *instr, bool returnedTuple)
{
- struct timeval endtime;
+ instr_time endtime;
if (!instr)
return;
- if (instr->starttime.tv_sec == 0 && instr->starttime.tv_usec == 0)
+ if (INSTR_TIME_IS_ZERO(instr->starttime))
{
elog(DEBUG2, "InstrStopNode without start");
return;
}
- gettimeofday(&endtime, NULL);
+ INSTR_TIME_SET_CURRENT(endtime);
+#ifndef WIN32
instr->counter.tv_sec += endtime.tv_sec - instr->starttime.tv_sec;
instr->counter.tv_usec += endtime.tv_usec - instr->starttime.tv_usec;
instr->counter.tv_usec -= 1000000;
instr->counter.tv_sec++;
}
+#else /* WIN32 */
+ instr->counter.QuadPart += (endtime.QuadPart - instr->starttime.QuadPart);
+#endif
- instr->starttime.tv_sec = 0;
- instr->starttime.tv_usec = 0;
+ INSTR_TIME_SET_ZERO(instr->starttime);
/* Is this the first tuple of this cycle? */
if (!instr->running)
{
instr->running = true;
- instr->firsttuple = (double) instr->counter.tv_sec +
- (double) instr->counter.tv_usec / 1000000.0;
+ instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
}
if (returnedTuple)
return;
/* Accumulate statistics */
- totaltime = (double) instr->counter.tv_sec +
- (double) instr->counter.tv_usec / 1000000.0;
+ totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
instr->startup += instr->firsttuple;
instr->total += totaltime;
/* Reset for next cycle (if any) */
instr->running = false;
- instr->starttime.tv_sec = 0;
- instr->starttime.tv_usec = 0;
- instr->counter.tv_sec = 0;
- instr->counter.tv_usec = 0;
+ INSTR_TIME_SET_ZERO(instr->starttime);
+ INSTR_TIME_SET_ZERO(instr->counter);
instr->firsttuple = 0;
instr->tuplecount = 0;
}
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.8 2005/01/01 05:43:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.9 2005/03/20 22:27:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include <sys/time.h>
+/*
+ * gettimeofday() does not have sufficient resolution on Windows,
+ * so we must use QueryPerformanceCounter() instead. These macros
+ * also give some breathing room to use other high-precision-timing APIs
+ * on yet other platforms. (The macro-ization is not complete, however;
+ * see subtraction code in instrument.c and explain.c.)
+ */
+#ifndef WIN32
+
+typedef struct timeval instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).tv_sec == 0 && (t).tv_usec == 0)
+#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
+#define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
+
+#else /* WIN32 */
+
+typedef LARGE_INTEGER instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
+#define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
+#define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).QuadPart) / GetTimerFrequency())
+
+static __inline__ double
+GetTimerFrequency(void)
+{
+ LARGE_INTEGER f;
+
+ QueryPerformanceFrequency(&f);
+ return (double) f.QuadPart;
+}
+
+#endif /* WIN32 */
+
+
typedef struct Instrumentation
{
/* Info about current plan cycle: */
bool running; /* TRUE if we've completed first tuple */
- struct timeval starttime; /* Start time of current iteration of node */
- struct timeval counter; /* Accumulates runtime for this node */
+ instr_time starttime; /* Start time of current iteration of node */
+ instr_time counter; /* Accumulates runtime for this node */
double firsttuple; /* Time for first tuple of this cycle */
double tuplecount; /* Tuples so far this cycle */
/* Accumulated statistics across all completed cycles: */