instr_time.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 gettimeofday(), but on Windows that
  8. * gives a low-precision result so we must use QueryPerformanceCounter()
  9. * instead. These macros also give some breathing room to use other
  10. * high-precision-timing APIs on yet other platforms.
  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_ADD(x, y) x += y
  24. *
  25. * INSTR_TIME_SUBTRACT(x, y) x -= y
  26. *
  27. * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z)
  28. *
  29. * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds)
  30. *
  31. * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds)
  32. *
  33. * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds)
  34. *
  35. * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
  36. * absolute times to intervals. The INSTR_TIME_GET_xxx operations are
  37. * only useful on intervals.
  38. *
  39. * When summing multiple measurements, it's recommended to leave the
  40. * running sum in instr_time form (ie, use INSTR_TIME_ADD or
  41. * INSTR_TIME_ACCUM_DIFF) and convert to a result format only at the end.
  42. *
  43. * Beware of multiple evaluations of the macro arguments.
  44. *
  45. *
  46. * Copyright (c) 2001-2016, PostgreSQL Global Development Group
  47. *
  48. * src/include/portability/instr_time.h
  49. *
  50. *-------------------------------------------------------------------------
  51. */
  52. #ifndef INSTR_TIME_H
  53. #define INSTR_TIME_H
  54. #ifndef WIN32
  55. #include <sys/time.h>
  56. typedef struct timeval instr_time;
  57. #define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0)
  58. #define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
  59. #define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
  60. #define INSTR_TIME_ADD(x,y) \
  61. do { \
  62. (x).tv_sec += (y).tv_sec; \
  63. (x).tv_usec += (y).tv_usec; \
  64. /* Normalize */ \
  65. while ((x).tv_usec >= 1000000) \
  66. { \
  67. (x).tv_usec -= 1000000; \
  68. (x).tv_sec++; \
  69. } \
  70. } while (0)
  71. #define INSTR_TIME_SUBTRACT(x,y) \
  72. do { \
  73. (x).tv_sec -= (y).tv_sec; \
  74. (x).tv_usec -= (y).tv_usec; \
  75. /* Normalize */ \
  76. while ((x).tv_usec < 0) \
  77. { \
  78. (x).tv_usec += 1000000; \
  79. (x).tv_sec--; \
  80. } \
  81. } while (0)
  82. #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
  83. do { \
  84. (x).tv_sec += (y).tv_sec - (z).tv_sec; \
  85. (x).tv_usec += (y).tv_usec - (z).tv_usec; \
  86. /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
  87. while ((x).tv_usec < 0) \
  88. { \
  89. (x).tv_usec += 1000000; \
  90. (x).tv_sec--; \
  91. } \
  92. while ((x).tv_usec >= 1000000) \
  93. { \
  94. (x).tv_usec -= 1000000; \
  95. (x).tv_sec++; \
  96. } \
  97. } while (0)
  98. #define INSTR_TIME_GET_DOUBLE(t) \
  99. (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
  100. #define INSTR_TIME_GET_MILLISEC(t) \
  101. (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
  102. #define INSTR_TIME_GET_MICROSEC(t) \
  103. (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
  104. #else /* WIN32 */
  105. typedef LARGE_INTEGER instr_time;
  106. #define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
  107. #define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
  108. #define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
  109. #define INSTR_TIME_ADD(x,y) \
  110. ((x).QuadPart += (y).QuadPart)
  111. #define INSTR_TIME_SUBTRACT(x,y) \
  112. ((x).QuadPart -= (y).QuadPart)
  113. #define INSTR_TIME_ACCUM_DIFF(x,y,z) \
  114. ((x).QuadPart += (y).QuadPart - (z).QuadPart)
  115. #define INSTR_TIME_GET_DOUBLE(t) \
  116. (((double) (t).QuadPart) / GetTimerFrequency())
  117. #define INSTR_TIME_GET_MILLISEC(t) \
  118. (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
  119. #define INSTR_TIME_GET_MICROSEC(t) \
  120. ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
  121. static inline double
  122. GetTimerFrequency(void)
  123. {
  124. LARGE_INTEGER f;
  125. QueryPerformanceFrequency(&f);
  126. return (double) f.QuadPart;
  127. }
  128. #endif /* WIN32 */
  129. #endif /* INSTR_TIME_H */