From 4a3886cfd6169df70ed1487d4c7029b5588658a2 Mon Sep 17 00:00:00 2001
From: Lukas Fittl <lukas@fittl.com>
Date: Tue, 24 Feb 2026 23:44:28 -0800
Subject: [PATCH v9 4/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_SET_NANOSEC macro that allows initializing an instr_time
variable from a user-defined interval.

Author: Lukas Fittl <lukas@fittl.com>
Reviewed-by:
Discussion:
---
 src/bin/pg_test_timing/pg_test_timing.c | 29 ++++++++++++++-----------
 src/include/portability/instr_time.h    |  4 +++-
 2 files changed, 19 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..dd865ed8875 100644
--- a/src/bin/pg_test_timing/pg_test_timing.c
+++ b/src/bin/pg_test_timing/pg_test_timing.c
@@ -152,14 +152,12 @@ 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;
+				duration_time,
+				prev,
+				cur;
 
 	/*
 	 * Pre-zero the statistics data structures.  They're already zero by
@@ -171,20 +169,26 @@ test_timing(unsigned int duration)
 	largest_diff = 0;
 	largest_diff_count = 0;
 
-	total_time = duration > 0 ? duration * INT64CONST(1000000000) : 0;
+	INSTR_TIME_SET_NANOSEC(duration_time, duration > 0 ? duration * NS_PER_S : 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(end_time, duration_time);
+
+	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 +221,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..1b0c8e28f9b 100644
--- a/src/include/portability/instr_time.h
+++ b/src/include/portability/instr_time.h
@@ -17,8 +17,9 @@
  *
  * INSTR_TIME_SET_ZERO(t)			set t to zero (memset is acceptable too)
  *
- * INSTR_TIME_SET_CURRENT(t)		set t to current time
+ * INSTR_TIME_SET_NANOSEC(t, x)		set t to the specified value (in nanosecs)
  *
+ * INSTR_TIME_SET_CURRENT(t)		set t to current time
  *
  * INSTR_TIME_ADD(x, y)				x += y
  *
@@ -170,6 +171,7 @@ GetTimerFrequency(void)
 
 #define INSTR_TIME_SET_ZERO(t)	((t).ticks = 0)
 
+#define INSTR_TIME_SET_NANOSEC(t, n)	((t).ticks = n)
 
 #define INSTR_TIME_ADD(x,y) \
 	((x).ticks += (y).ticks)
-- 
2.47.1

