LCOV - code coverage report
Current view: top level - src/include/portability - instr_time.h (source / functions) Coverage Total Hit
Test: Code coverage Lines: 100.0 % 5 5
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.3.2-1