instr_time endtime;
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--;
- }
-#else /* WIN32 */
- endtime.QuadPart -= starttime->QuadPart;
-#endif
-
+ INSTR_TIME_SUBTRACT(endtime, *starttime);
return INSTR_TIME_GET_DOUBLE(endtime);
}
}
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;
-
- /* Normalize after each add to avoid overflow/underflow of tv_usec */
- while (instr->counter.tv_usec < 0)
- {
- instr->counter.tv_usec += 1000000;
- instr->counter.tv_sec--;
- }
- while (instr->counter.tv_usec >= 1000000)
- {
- instr->counter.tv_usec -= 1000000;
- instr->counter.tv_sec++;
- }
-#else /* WIN32 */
- instr->counter.QuadPart += (endtime.QuadPart - instr->starttime.QuadPart);
-#endif
+ INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime);
INSTR_TIME_SET_ZERO(instr->starttime);
#include <sys/stat.h> /* for stat() */
#endif
+#include "portability/instr_time.h"
+
#include "libpq-fe.h"
#include "pqexpbuffer.h"
#include "dumputils.h"
else if (pg_strcasecmp(cmd, "copy") == 0)
{
/* Default fetch-it-all-and-print mode */
- TimevalStruct before,
+ instr_time before,
after;
- double elapsed_msec = 0;
char *opt = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, false);
if (pset.timing)
- GETTIMEOFDAY(&before);
+ INSTR_TIME_SET_CURRENT(before);
success = do_copy(opt);
if (pset.timing && success)
{
- GETTIMEOFDAY(&after);
- elapsed_msec = DIFF_MSEC(&after, &before);
- printf(_("Time: %.3f ms\n"), elapsed_msec);
-
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ printf(_("Time: %.3f ms\n"), INSTR_TIME_GET_MILLISEC(after));
}
free(opt);
#include <win32.h>
#endif
+#include "portability/instr_time.h"
+
#include "pqsignal.h"
#include "settings.h"
if (pset.fetch_count <= 0 || !is_select_command(query))
{
/* Default fetch-it-all-and-print mode */
- TimevalStruct before,
+ instr_time before,
after;
if (pset.timing)
- GETTIMEOFDAY(&before);
+ INSTR_TIME_SET_CURRENT(before);
results = PQexec(pset.db, query);
if (pset.timing)
{
- GETTIMEOFDAY(&after);
- elapsed_msec = DIFF_MSEC(&after, &before);
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
}
/* but printing results isn't: */
bool did_pager = false;
int ntuples;
char fetch_cmd[64];
- TimevalStruct before,
+ instr_time before,
after;
*elapsed_msec = 0;
my_popt.topt.prior_records = 0;
if (pset.timing)
- GETTIMEOFDAY(&before);
+ INSTR_TIME_SET_CURRENT(before);
/* if we're not in a transaction, start one */
if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
if (pset.timing)
{
- GETTIMEOFDAY(&after);
- *elapsed_msec += DIFF_MSEC(&after, &before);
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
}
snprintf(fetch_cmd, sizeof(fetch_cmd),
for (;;)
{
if (pset.timing)
- GETTIMEOFDAY(&before);
+ INSTR_TIME_SET_CURRENT(before);
/* get FETCH_COUNT tuples at a time */
results = PQexec(pset.db, fetch_cmd);
if (pset.timing)
{
- GETTIMEOFDAY(&after);
- *elapsed_msec += DIFF_MSEC(&after, &before);
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
}
if (PQresultStatus(results) != PGRES_TUPLES_OK)
cleanup:
if (pset.timing)
- GETTIMEOFDAY(&before);
+ INSTR_TIME_SET_CURRENT(before);
/*
* We try to close the cursor on either success or failure, but on failure
if (pset.timing)
{
- GETTIMEOFDAY(&after);
- *elapsed_msec += DIFF_MSEC(&after, &before);
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
}
return OK;
extern char *expand_tilde(char **filename);
-#ifndef WIN32
-
-#include <sys/time.h>
-
-typedef struct timeval TimevalStruct;
-
-#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
-#define DIFF_MSEC(T, U) \
- ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
- ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
-#else
-/*
- * To get good resolution (better than ~15ms) on Windows, use
- * the high resolution performance counters. They can't be used
- * to get absolute times, but are good for measuring differences.
- */
-static __inline__ double
-GetTimerFrequency(void)
-{
- LARGE_INTEGER f;
-
- QueryPerformanceFrequency(&f);
- return (double) f.QuadPart;
-}
-
-typedef LARGE_INTEGER TimevalStruct;
-
-#define GETTIMEOFDAY(T) QueryPerformanceCounter((T))
-#define DIFF_MSEC(T, U) \
- (((T)->QuadPart - (U)->QuadPart) * 1000.0 / GetTimerFrequency())
-#endif /* WIN32 */
-
#endif /* COMMON_H */
nodes optimizer parser postmaster regex rewrite storage tcop \
snowball snowball/libstemmer tsearch tsearch/dicts utils \
port port/win32 port/win32_msvc port/win32_msvc/sys \
- port/win32/arpa port/win32/netinet port/win32/sys
+ port/win32/arpa port/win32/netinet port/win32/sys \
+ portability
# Install all headers
install: all installdirs
#ifndef INSTRUMENT_H
#define INSTRUMENT_H
-#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 */
+#include "portability/instr_time.h"
typedef struct Instrumentation
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * instr_time.h
+ * portable high-precision interval timing
+ *
+ * This file provides an abstraction layer to hide portability issues in
+ * interval timing. On Unix we use gettimeofday(), but on Windows that
+ * gives a low-precision result 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 basic data type is instr_time, which all callers should treat as an
+ * opaque typedef. instr_time can store either an absolute time (of
+ * unspecified reference time) or an interval. The operations provided
+ * for it are:
+ *
+ * INSTR_TIME_IS_ZERO(t) is t equal to zero?
+ *
+ * INSTR_TIME_SET_ZERO(t) set t to zero (memset is acceptable too)
+ *
+ * INSTR_TIME_SET_CURRENT(t) set t to current time
+ *
+ * INSTR_TIME_SUBTRACT(x, y) x -= y
+ *
+ * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z)
+ *
+ * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds)
+ *
+ * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds)
+ *
+ * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds)
+ *
+ * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
+ * absolute times to intervals. The INSTR_TIME_GET_xxx operations are
+ * only useful on intervals.
+ *
+ * When summing multiple measurements, it's recommended to leave the
+ * running sum in instr_time form (ie, use INSTR_TIME_ACCUM_DIFF) and
+ * convert to a result format only at the end.
+ *
+ * Beware of multiple evaluations of the macro arguments.
+ *
+ *
+ * Copyright (c) 2001-2008, PostgreSQL Global Development Group
+ *
+ * $PostgreSQL$
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INSTR_TIME_H
+#define INSTR_TIME_H
+
+#ifndef WIN32
+
+#include <sys/time.h>
+
+typedef struct timeval instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 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_SUBTRACT(x,y) \
+ do { \
+ (x).tv_sec -= (y).tv_sec; \
+ (x).tv_usec -= (y).tv_usec; \
+ /* Normalize */ \
+ while ((x).tv_usec < 0) \
+ { \
+ (x).tv_usec += 1000000; \
+ (x).tv_sec--; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
+ do { \
+ (x).tv_sec += (y).tv_sec - (z).tv_sec; \
+ (x).tv_usec += (y).tv_usec - (z).tv_usec; \
+ /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
+ while ((x).tv_usec < 0) \
+ { \
+ (x).tv_usec += 1000000; \
+ (x).tv_sec--; \
+ } \
+ while ((x).tv_usec >= 1000000) \
+ { \
+ (x).tv_usec -= 1000000; \
+ (x).tv_sec++; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
+
+#define INSTR_TIME_GET_MILLISEC(t) \
+ (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
+
+#define INSTR_TIME_GET_MICROSEC(t) \
+ (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
+
+#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_SUBTRACT(x,y) \
+ ((x).QuadPart -= (y).QuadPart)
+
+#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
+ ((x).QuadPart += (y).QuadPart - (z).QuadPart)
+
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).QuadPart) / GetTimerFrequency())
+
+#define INSTR_TIME_GET_MILLISEC(t) \
+ (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
+
+#define INSTR_TIME_GET_MICROSEC(t) \
+ ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
+
+static __inline__ double
+GetTimerFrequency(void)
+{
+ LARGE_INTEGER f;
+
+ QueryPerformanceFrequency(&f);
+ return (double) f.QuadPart;
+}
+
+#endif /* WIN32 */
+
+#endif /* INSTR_TIME_H */