instr_time.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*-------------------------------------------------------------------------
  2. *
  3. * instr_time.h
  4. * portable high-precision interval timing
  5. *
  6. * This file provides an abstraction layer to hide portability issues in
  7. * interval timing. On Unix we use clock_gettime() if available, else
  8. * gettimeofday(). On Windows, gettimeofday() gives a low-precision result
  9. * so we must use QueryPerformanceCounter() instead. These macros also give
  10. * some breathing room to use other high-precision-timing APIs.
  11. *
  12. * The basic data type is instr_time, which all callers should treat as an
  13. * opaque typedef. instr_time can store either an absolute time (of
  14. * unspecified reference time) or an interval. The operations provided
  15. * for it are:
  16. *
  17. * INSTR_TIME_IS_ZERO(t) is t equal to zero?
  18. *
  19. * INSTR_TIME_SET_ZERO(t) set t to zero (memset is acceptable too)
  20. *
  21. * INSTR_TIME_SET_CURRENT(t) set t to current time
  22. *
  23. * INSTR_TIME_SET_CURRENT_LAZY(t) set t to current time if t is zero,
  24. * evaluates to whether t changed
  25. *
  26. * INSTR_TIME_ADD(x, y) x += y
  27. *
  28. * INSTR_TIME_SUBTRACT(x, y) x -= y
  29. *
  30. * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z)
  31. *
  32. * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds)
  33. *
  34. * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds)
  35. *
  36. * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds)
  37. *
  38. * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
  39. * absolute times to intervals. The INSTR_TIME_GET_xxx operations are
  40. * only useful on intervals.
  41. *
  42. * When summing multiple measurements, it's recommended to leave the
  43. * running sum in instr_time form (ie, use INSTR_TIME_ADD or
  44. * INSTR_TIME_ACCUM_DIFF) and convert to a result format only at the end.
  45. *
  46. * Beware of multiple evaluations of the macro arguments.
  47. *
  48. *
  49. * Copyright (c) 2001-2022, PostgreSQL Global Development Group
  50. *
  51. * src/include/portability/instr_time.h
  52. *
  53. *-------------------------------------------------------------------------
  54. */
  55. #ifndef INSTR_TIME_H
  56. #define INSTR_TIME_H
  57. #ifndef WIN32
  58. #ifdef HAVE_CLOCK_GETTIME
  59. /* Use clock_gettime() */
  60. #include <time.h>
  61. /*
  62. * The best clockid to use according to the POSIX spec is CLOCK_MONOTONIC,
  63. * since that will give reliable interval timing even in the face of changes
  64. * to the system clock. However, POSIX doesn't require implementations to
  65. * provide anything except CLOCK_REALTIME, so fall back to that if we don't
  66. * find CLOCK_MONOTONIC.
  67. *
  68. * Also, some implementations have nonstandard clockids with better properties
  69. * than CLOCK_MONOTONIC. In particular, as of macOS 10.12, Apple provides
  70. * CLOCK_MONOTONIC_RAW which is both faster to read and higher resolution than
  71. * their version of CLOCK_MONOTONIC.
  72. */
  73. #if defined(__darwin__) && defined(CLOCK_MONOTONIC_RAW)
  74. #define PG_INSTR_CLOCK CLOCK_MONOTONIC_RAW
  75. #elif defined(CLOCK_MONOTONIC)
  76. #define PG_INSTR_CLOCK CLOCK_MONOTONIC
  77. #else
  78. #define PG_INSTR_CLOCK CLOCK_REALTIME
  79. #endif
  80. typedef struct timespec instr_time;
  81. #define INSTR_TIME_IS_ZERO(t) ((t).tv_nsec == 0 && (t).tv_sec == 0)
  82. #define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_nsec = 0)
  83. #define INSTR_TIME_SET_CURRENT(t) ((void) clock_gettime(PG_INSTR_CLOCK, &(t)))
  84. #define INSTR_TIME_ADD(x,y) \
  85. do { \
  86. (x).tv_sec += (y).tv_sec; \
  87. (x).tv_nsec += (y).tv_nsec; \
  88. /* Normalize */ \
  89. while ((x).tv_nsec >= 1000000000) \
  90. { \
  91. (x).tv_nsec -= 1000000000; \
  92. (x).tv_sec++; \
  93. } \
  94. } while (0)
  95. #define INSTR_TIME_SUBTRACT(x,y) \
  96. do { \
  97. (x).tv_sec -= (y).tv_sec; \
  98. (x).tv_nsec -= (y).tv_nsec; \
  99. /* Normalize */ \
  100. while ((x).tv_nsec < 0) \
  101. { \
  102. (x).tv_nsec += 1000000000; \
  103. (x).tv_sec--; \
  104. } \
  105. } while (0)
  106. #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
  107. do { \
  108. (x).tv_sec += (y).tv_sec - (z).tv_sec; \
  109. (x).tv_nsec += (y).tv_nsec - (z).tv_nsec; \
  110. /* Normalize after each add to avoid overflow/underflow of tv_nsec */ \
  111. while ((x).tv_nsec < 0) \
  112. { \
  113. (x).tv_nsec += 1000000000; \
  114. (x).tv_sec--; \
  115. } \
  116. while ((x).tv_nsec >= 1000000000) \
  117. { \
  118. (x).tv_nsec -= 1000000000; \
  119. (x).tv_sec++; \
  120. } \
  121. } while (0)
  122. #define INSTR_TIME_GET_DOUBLE(t) \
  123. (((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
  124. #define INSTR_TIME_GET_MILLISEC(t) \
  125. (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
  126. #define INSTR_TIME_GET_MICROSEC(t) \
  127. (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
  128. #else /* !HAVE_CLOCK_GETTIME */
  129. /* Use gettimeofday() */
  130. #include <sys/time.h>
  131. typedef struct timeval instr_time;
  132. #define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0)
  133. #define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
  134. #define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
  135. #define INSTR_TIME_ADD(x,y) \
  136. do { \
  137. (x).tv_sec += (y).tv_sec; \
  138. (x).tv_usec += (y).tv_usec; \
  139. /* Normalize */ \
  140. while ((x).tv_usec >= 1000000) \
  141. { \
  142. (x).tv_usec -= 1000000; \
  143. (x).tv_sec++; \
  144. } \
  145. } while (0)
  146. #define INSTR_TIME_SUBTRACT(x,y) \
  147. do { \
  148. (x).tv_sec -= (y).tv_sec; \
  149. (x).tv_usec -= (y).tv_usec; \
  150. /* Normalize */ \
  151. while ((x).tv_usec < 0) \
  152. { \
  153. (x).tv_usec += 1000000; \
  154. (x).tv_sec--; \
  155. } \
  156. } while (0)
  157. #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
  158. do { \
  159. (x).tv_sec += (y).tv_sec - (z).tv_sec; \
  160. (x).tv_usec += (y).tv_usec - (z).tv_usec; \
  161. /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
  162. while ((x).tv_usec < 0) \
  163. { \
  164. (x).tv_usec += 1000000; \
  165. (x).tv_sec--; \
  166. } \
  167. while ((x).tv_usec >= 1000000) \
  168. { \
  169. (x).tv_usec -= 1000000; \
  170. (x).tv_sec++; \
  171. } \
  172. } while (0)
  173. #define INSTR_TIME_GET_DOUBLE(t) \
  174. (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
  175. #define INSTR_TIME_GET_MILLISEC(t) \
  176. (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
  177. #define INSTR_TIME_GET_MICROSEC(t) \
  178. (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
  179. #endif /* HAVE_CLOCK_GETTIME */
  180. #else /* WIN32 */
  181. /* Use QueryPerformanceCounter() */
  182. typedef LARGE_INTEGER instr_time;
  183. #define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
  184. #define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
  185. #define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
  186. #define INSTR_TIME_ADD(x,y) \
  187. ((x).QuadPart += (y).QuadPart)
  188. #define INSTR_TIME_SUBTRACT(x,y) \
  189. ((x).QuadPart -= (y).QuadPart)
  190. #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
  191. ((x).QuadPart += (y).QuadPart - (z).QuadPart)
  192. #define INSTR_TIME_GET_DOUBLE(t) \
  193. (((double) (t).QuadPart) / GetTimerFrequency())
  194. #define INSTR_TIME_GET_MILLISEC(t) \
  195. (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
  196. #define INSTR_TIME_GET_MICROSEC(t) \
  197. ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
  198. static inline double
  199. GetTimerFrequency(void)
  200. {
  201. LARGE_INTEGER f;
  202. QueryPerformanceFrequency(&f);
  203. return (double) f.QuadPart;
  204. }
  205. #endif /* WIN32 */
  206. /* same macro on all platforms */
  207. #define INSTR_TIME_SET_CURRENT_LAZY(t) \
  208. (INSTR_TIME_IS_ZERO(t) ? INSTR_TIME_SET_CURRENT(t), true : false)
  209. #endif /* INSTR_TIME_H */