摘自PostgreSQL 11源码src/include/portability/instr_time.h.
- linux不用做任何修改可在C/C++程序中直接使用.
- windows 需要在在instr_time.h第207行后添加windows头文件#include <windows.h>,同时需要定义宏WIN32.
使用方法
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "instr_time.h"
#define gettext(x) (x)
#define _(x) gettext(x)
//PrintTiming在src\bin\psql\common.c(775)
static void PrintTiming(double elapsed_msec) {
double seconds;
double minutes;
double hours;
double days;
if (elapsed_msec < 1000.0) {
/* This is the traditional (pre-v10) output format */
printf(_("Time: %.3f ms\n"), elapsed_msec);
return;
}
/*
* Note: we could print just seconds, in a format like %06.3f, when the
* total is less than 1min. But that's hard to interpret unless we tack
* on "s" or otherwise annotate it. Forcing the display to include
* minutes seems like a better solution.
*/
seconds = elapsed_msec / 1000.0;
minutes = floor(seconds / 60.0);
seconds -= 60.0 * minutes;
if (minutes < 60.0) {
printf(_("Time: %.3f ms (%02d:%06.3f)\n"),
elapsed_msec, (int)minutes, seconds);
return;
}
hours = floor(minutes / 60.0);
minutes -= 60.0 * hours;
if (hours < 24.0) {
printf(_("Time: %.3f ms (%02d:%02d:%06.3f)\n"),
elapsed_msec, (int)hours, (int)minutes, seconds);
return;
}
days = floor(hours / 24.0);
hours -= 24.0 * days;
printf(_("Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n"),
elapsed_msec, days, (int)hours, (int)minutes, seconds);
}
int main(int argc, char** argv) {
int i = 0, val = 0;
instr_time before, after;
double elapsed_msec = 0;
INSTR_TIME_SET_CURRENT(before);
/*获取PostgreSQL数据库的状态*/
for (i = 0; i < 1000000; ++i) {
val++;
}
INSTR_TIME_SET_CURRENT(after);
INSTR_TIME_SUBTRACT(after, before);
elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
PrintTiming(elapsed_msec);
exit(EXIT_SUCCESS);
}
源码:src/include/portability/instr_time.
/*-------------------------------------------------------------------------
*
* 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 clock_gettime() if available, else
* gettimeofday(). On Windows, gettimeofday() 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.
*
* 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_ADD(x, y) x += y
*
* 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_ADD or
* 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-2018, PostgreSQL Global Development Group
*
* src/include/portability/instr_time.h
*
*-------------------------------------------------------------------------
*/
#ifndef INSTR_TIME_H
#define INSTR_TIME_H
#ifndef WIN32
#ifdef HAVE_CLOCK_GETTIME
/* Use clock_gettime() */
#include <time.h>
/*
* The best clockid to use according to the POSIX spec is CLOCK_MONOTONIC,
* since that will give reliable interval timing even in the face of changes
* to the system clock. However, POSIX doesn't require implementations to
* provide anything except CLOCK_REALTIME, so fall back to that if we don't
* find CLOCK_MONOTONIC.
*
* Also, some implementations have nonstandard clockids with better properties
* than CLOCK_MONOTONIC. In particular, as of macOS 10.12, Apple provides
* CLOCK_MONOTONIC_RAW which is both faster to read and higher resolution than
* their version of CLOCK_MONOTONIC.
*/
#if defined(__darwin__) && defined(CLOCK_MONOTONIC_RAW)
#define PG_INSTR_CLOCK CLOCK_MONOTONIC_RAW
#elif defined(CLOCK_MONOTONIC)
#define PG_INSTR_CLOCK CLOCK_MONOTONIC
#else
#define PG_INSTR_CLOCK CLOCK_REALTIME
#endif
typedef struct timespec instr_time;
#define INSTR_TIME_IS_ZERO(t) ((t).tv_nsec == 0 && (t).tv_sec == 0)
#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_nsec = 0)
#define INSTR_TIME_SET_CURRENT(t) ((void) clock_gettime(PG_INSTR_CLOCK, &(t)))
#define INSTR_TIME_ADD(x,y) \
do { \
(x).tv_sec += (y).tv_sec; \
(x).tv_nsec += (y).tv_nsec; \
/* Normalize */ \
while ((x).tv_nsec >= 1000000000) \
{ \
(x).tv_nsec -= 1000000000; \
(x).tv_sec++; \
} \
} while (0)
#define INSTR_TIME_SUBTRACT(x,y) \
do { \
(x).tv_sec -= (y).tv_sec; \
(x).tv_nsec -= (y).tv_nsec; \
/* Normalize */ \
while ((x).tv_nsec < 0) \
{ \
(x).tv_nsec += 1000000000; \
(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_nsec += (y).tv_nsec - (z).tv_nsec; \
/* Normalize after each add to avoid overflow/underflow of tv_nsec */ \
while ((x).tv_nsec < 0) \
{ \
(x).tv_nsec += 1000000000; \
(x).tv_sec--; \
} \
while ((x).tv_nsec >= 1000000000) \
{ \
(x).tv_nsec -= 1000000000; \
(x).tv_sec++; \
} \
} while (0)
#define INSTR_TIME_GET_DOUBLE(t) \
(((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
#define INSTR_TIME_GET_MILLISEC(t) \
(((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
#define INSTR_TIME_GET_MICROSEC(t) \
(((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
#else /* !HAVE_CLOCK_GETTIME */
/* Use gettimeofday() */
#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_ADD(x,y) \
do { \
(x).tv_sec += (y).tv_sec; \
(x).tv_usec += (y).tv_usec; \
/* Normalize */ \
while ((x).tv_usec >= 1000000) \
{ \
(x).tv_usec -= 1000000; \
(x).tv_sec++; \
} \
} while (0)
#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)
#endif /* HAVE_CLOCK_GETTIME */
#else /* WIN32 */
#include <windows.h> //添加windows头文件
/* Use QueryPerformanceCounter() */
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_ADD(x,y) \
((x).QuadPart += (y).QuadPart)
#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 */