From ba1d96e64f0eae8833ce17149f9c78c549abc073 Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Tue, 24 Feb 2026 23:44:28 -0800 Subject: [PATCH v12 3/7] pg_test_timing: Reduce per-loop overhead The pg_test_timing program was previously using INSTR_TIME_GET_NANOSEC on an absolute instr_time value in order to do a diff, which goes against the spirit of how the GET_* macros are supposed to be used, and will cause overhead in a future change that assumes these macros are typically used on intervals only. Additionally the program was doing unnecessary work in the test loop by measuring the time elapsed, instead of checking the existing current time measurement against a target end time. To support that, introduce a new INSTR_TIME_ADD_NANOSEC macro that allows adding user-defined nanoseconds to an instr_time variable. Author: Lukas Fittl Reviewed-by: Discussion: --- src/bin/pg_test_timing/pg_test_timing.c | 28 ++++++++++++------------- src/include/portability/instr_time.h | 8 +++++++ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/bin/pg_test_timing/pg_test_timing.c b/src/bin/pg_test_timing/pg_test_timing.c index a5621251afc..264903ebbf6 100644 --- a/src/bin/pg_test_timing/pg_test_timing.c +++ b/src/bin/pg_test_timing/pg_test_timing.c @@ -152,14 +152,11 @@ handle_args(int argc, char *argv[]) static uint64 test_timing(unsigned int duration) { - uint64 total_time; - int64 time_elapsed = 0; uint64 loop_count = 0; - uint64 prev, - cur; instr_time start_time, end_time, - temp; + prev, + cur; /* * Pre-zero the statistics data structures. They're already zero by @@ -171,20 +168,24 @@ test_timing(unsigned int duration) largest_diff = 0; largest_diff_count = 0; - total_time = duration > 0 ? duration * INT64CONST(1000000000) : 0; - INSTR_TIME_SET_CURRENT(start_time); - cur = INSTR_TIME_GET_NANOSEC(start_time); + cur = start_time; - while (time_elapsed < total_time) + end_time = start_time; + INSTR_TIME_ADD_NANOSEC(end_time, duration > 0 ? duration * NS_PER_S : 0); + + while (INSTR_TIME_GT(end_time, cur)) { int32 diff, bits; + instr_time diff_time; prev = cur; - INSTR_TIME_SET_CURRENT(temp); - cur = INSTR_TIME_GET_NANOSEC(temp); - diff = cur - prev; + INSTR_TIME_SET_CURRENT(cur); + + diff_time = cur; + INSTR_TIME_SUBTRACT(diff_time, prev); + diff = INSTR_TIME_GET_NANOSEC(diff_time); /* Did time go backwards? */ if (unlikely(diff < 0)) @@ -217,10 +218,9 @@ test_timing(unsigned int duration) largest_diff_count++; loop_count++; - INSTR_TIME_SUBTRACT(temp, start_time); - time_elapsed = INSTR_TIME_GET_NANOSEC(temp); } + /* Refresh end time to be the actual time spent (vs the target end time) */ INSTR_TIME_SET_CURRENT(end_time); INSTR_TIME_SUBTRACT(end_time, start_time); diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h index 8b6baeffd3e..0a1fff7c487 100644 --- a/src/include/portability/instr_time.h +++ b/src/include/portability/instr_time.h @@ -22,6 +22,8 @@ * * INSTR_TIME_ADD(x, y) x += y * + * INSTR_TIME_ADD_NANOSEC(t, n) x += y in nanoseconds (converts to ticks) + * * INSTR_TIME_SUBTRACT(x, y) x -= y * * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z) @@ -125,6 +127,9 @@ pg_clock_gettime_ns(void) #define INSTR_TIME_GET_NANOSEC(t) \ ((int64) (t).ticks) +#define INSTR_TIME_ADD_NANOSEC(t, n) \ + ((t).ticks += (n)) + #else /* WIN32 */ @@ -159,6 +164,9 @@ GetTimerFrequency(void) #define INSTR_TIME_GET_NANOSEC(t) \ ((int64) ((t).ticks * ((double) NS_PER_S / GetTimerFrequency()))) +#define INSTR_TIME_ADD_NANOSEC(t, n) \ + ((t).ticks += ((n) / ((double) NS_PER_S / GetTimerFrequency()))) + #endif /* WIN32 */ -- 2.47.1