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

Generated by: LCOV version 2.0-1