v9-0007-pg_test_timing-Also-test-RDTSC-RDTSCP-timing-and-.patch
application/octet-stream
Filename: v9-0007-pg_test_timing-Also-test-RDTSC-RDTSCP-timing-and-.patch
Type: application/octet-stream
Part: 6
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v9-0007
Subject: pg_test_timing: Also test RDTSC/RDTSCP timing and report time source
| File | + | − |
|---|---|---|
| src/bin/pg_test_timing/pg_test_timing.c | 87 | 9 |
| src/include/portability/instr_time.h | 6 | 0 |
From c3cdc0d18a37c77c18f9258c31be3e52660103f5 Mon Sep 17 00:00:00 2001
From: Lukas Fittl <lukas@fittl.com>
Date: Thu, 12 Feb 2026 01:12:19 -0800
Subject: [PATCH v9 7/7] pg_test_timing: Also test RDTSC/RDTSCP timing and
report time source
Author: David Geier <geidav.pg@gmail.com>
Author: Lukas Fittl <lukas@fittl.com>
Reviewed-by:
Discussion: https://www.postgresql.org/message-id/flat/20200612232810.f46nbqkdhbutzqdg%40alap3.anarazel.de
---
src/bin/pg_test_timing/pg_test_timing.c | 96 ++++++++++++++++++++++---
src/include/portability/instr_time.h | 6 ++
2 files changed, 93 insertions(+), 9 deletions(-)
diff --git a/src/bin/pg_test_timing/pg_test_timing.c b/src/bin/pg_test_timing/pg_test_timing.c
index 98672ae5d32..cfc5450b030 100644
--- a/src/bin/pg_test_timing/pg_test_timing.c
+++ b/src/bin/pg_test_timing/pg_test_timing.c
@@ -30,14 +30,16 @@ static long long int largest_diff_count;
static void handle_args(int argc, char *argv[]);
-static uint64 test_timing(unsigned int duration);
+static void test_system_timing(void);
+#if PG_INSTR_TSC_CLOCK
+static void test_tsc_timing(void);
+#endif
+static uint64 test_timing(unsigned int duration, TimingClockSourceType source, bool fast_timing);
static void output(uint64 loop_count);
int
main(int argc, char *argv[])
{
- uint64 loop_count;
-
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_test_timing"));
progname = get_progname(argv[0]);
@@ -46,9 +48,11 @@ main(int argc, char *argv[])
/* initialize timing infrastructure (required for INSTR_* calls) */
pg_initialize_timing();
- loop_count = test_timing(test_duration);
+ test_system_timing();
- output(loop_count);
+#if PG_INSTR_TSC_CLOCK
+ test_tsc_timing();
+#endif
return 0;
}
@@ -146,14 +150,66 @@ handle_args(int argc, char *argv[])
exit(1);
}
- printf(ngettext("Testing timing overhead for %u second.\n",
- "Testing timing overhead for %u seconds.\n",
+ printf(ngettext("Testing timing overhead for %u second.\n\n",
+ "Testing timing overhead for %u seconds.\n\n",
test_duration),
test_duration);
}
+/*
+ * This tests default (non-fast) timing code. A clock source for that is
+ * always available. Hence, we can unconditionally output the result.
+ */
+static void
+test_system_timing(void)
+{
+ uint64 loop_count;
+
+ loop_count = test_timing(test_duration, TIMING_CLOCK_SOURCE_SYSTEM, false);
+ output(loop_count);
+}
+
+/*
+ * If on a supported architecture, test the TSC clock source. This clock
+ * source is not always available. In that case we print an informational
+ * message indicating as such.
+ *
+ * We first emit "slow" timings (RDTSCP on x86), which are used for higher
+ * precision measurements when the TSC clock source is enabled. We emit
+ * "fast" timings second (RDTSC on x86), which is used for faster timing
+ * measurements with lower precision.
+ */
+#if PG_INSTR_TSC_CLOCK
+static void
+test_tsc_timing(void)
+{
+ uint64 loop_count;
+
+ printf("\n");
+ loop_count = test_timing(test_duration, TIMING_CLOCK_SOURCE_TSC, false);
+ if (loop_count > 0)
+ {
+ output(loop_count);
+ printf("\n");
+
+ /* Now, emit fast timing measurements */
+ loop_count = test_timing(test_duration, TIMING_CLOCK_SOURCE_TSC, true);
+ output(loop_count);
+ printf("\n");
+
+ pg_set_timing_clock_source(TIMING_CLOCK_SOURCE_AUTO);
+ if (pg_current_timing_clock_source() == TIMING_CLOCK_SOURCE_TSC)
+ printf(_("TSC clock source will be used by default, unless timing_clock_source is set to 'system'.\n"));
+ else
+ printf(_("TSC clock source will not be used by default, unless timing_clock_source is set to 'tsc'.\n"));
+ }
+ else
+ printf(_("TSC clock source is not usable. Likely unable to determine TSC frequency. are you running in an unsupported virtualized environment?.\n"));
+}
+#endif
+
static uint64
-test_timing(unsigned int duration)
+test_timing(unsigned int duration, TimingClockSourceType source, bool fast_timing)
{
uint64 loop_count = 0;
instr_time start_time,
@@ -161,6 +217,24 @@ test_timing(unsigned int duration)
duration_time,
prev,
cur;
+ char *time_source = NULL;
+
+ if (!pg_set_timing_clock_source(source))
+ return 0;
+
+ time_source = PG_INSTR_SYSTEM_CLOCK_NAME;
+
+#if PG_INSTR_TSC_CLOCK
+ if (pg_current_timing_clock_source() == TIMING_CLOCK_SOURCE_TSC)
+ time_source = fast_timing ? PG_INSTR_TSC_CLOCK_NAME_FAST : PG_INSTR_TSC_CLOCK_NAME;
+#endif
+
+ if (fast_timing)
+ printf(_("Fast clock source: %s\n"), time_source);
+ else if (source == TIMING_CLOCK_SOURCE_SYSTEM)
+ printf(_("System clock source: %s\n"), time_source);
+ else
+ printf(_("Clock source: %s\n"), time_source);
/*
* Pre-zero the statistics data structures. They're already zero by
@@ -187,7 +261,11 @@ test_timing(unsigned int duration)
instr_time diff_time;
prev = cur;
- INSTR_TIME_SET_CURRENT(cur);
+
+ if (fast_timing)
+ INSTR_TIME_SET_CURRENT_FAST(cur);
+ else
+ INSTR_TIME_SET_CURRENT(cur);
diff_time = cur;
INSTR_TIME_SUBTRACT(diff_time, prev);
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h
index 5b6e9195b41..c5d5ef1709f 100644
--- a/src/include/portability/instr_time.h
+++ b/src/include/portability/instr_time.h
@@ -126,6 +126,8 @@ extern bool pg_set_timing_clock_source(TimingClockSourceType source);
#if defined(__x86_64__) || defined(_M_X64)
#define PG_INSTR_TSC_CLOCK 1
+#define PG_INSTR_TSC_CLOCK_NAME_FAST "RDTSC"
+#define PG_INSTR_TSC_CLOCK_NAME "RDTSCP"
/* Whether to actually use TSC based on availability and GUC settings. */
extern PGDLLIMPORT bool use_tsc;
@@ -171,10 +173,13 @@ static inline TimingClockSourceType pg_current_timing_clock_source(void)
*/
#if defined(__darwin__) && defined(CLOCK_MONOTONIC_RAW)
#define PG_INSTR_SYSTEM_CLOCK CLOCK_MONOTONIC_RAW
+#define PG_INSTR_SYSTEM_CLOCK_NAME "clock_gettime (CLOCK_MONOTONIC_RAW)"
#elif defined(CLOCK_MONOTONIC)
#define PG_INSTR_SYSTEM_CLOCK CLOCK_MONOTONIC
+#define PG_INSTR_SYSTEM_CLOCK_NAME "clock_gettime (CLOCK_MONOTONIC)"
#else
#define PG_INSTR_SYSTEM_CLOCK CLOCK_REALTIME
+#define PG_INSTR_SYSTEM_CLOCK_NAME "clock_gettime (CLOCK_REALTIME)"
#endif
static inline instr_time
@@ -193,6 +198,7 @@ pg_get_ticks_system(void)
/* On Windows, use QueryPerformanceCounter() for system clock source */
+#define PG_INSTR_SYSTEM_CLOCK_NAME "QueryPerformanceCounter"
static inline instr_time
pg_get_ticks_system(void)
{
--
2.47.1