From ddb1adc5cd9acc9bc9de16d0cf057124b09fe1e3 Mon Sep 17 00:00:00 2001
From: Jehan-Guillaume de Rorthais <jgdr@dalibo.com>
Date: Fri, 4 Jun 2021 18:14:51 +0200
Subject: [PATCH 2/2] [POC] Change measuring method of wait event time from
 INSTR_TIME to rdtsc.

This patch changes measuring method of wait event time from INSTR_TIME (which
uses gettimeofday or clock_gettime) to rdtsc. This might reduce the overhead
of measuring overhead.

Any supports like changing clock cycle to actual time or error handling are
not currently implemented.
---
 src/backend/postmaster/pgstat.c         |  8 ++++----
 src/backend/utils/activity/wait_event.c | 10 +++++-----
 src/backend/utils/adt/pgstatfuncs.c     |  2 +-
 src/include/pgstat.h                    |  4 ++--
 src/include/portability/instr_time.h    | 21 +++++++++++++++++++++
 5 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index b4a84a2f62..e928239a29 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -180,7 +180,7 @@ static bool pgStatRunningInCollector = false;
 
 WAHash *wa_hash;
 
-instr_time waitStart;
+uint64 waitStart;
 
 /*
  * Structures in which backends store per-table info that's waiting to be
@@ -3332,7 +3332,7 @@ pgstat_send_waitaccum()
 
 		/* Clear wait events information. */
 		entry->calls = 0;
-		INSTR_TIME_SET_ZERO(entry->times);
+		entry->times = 0;
 	}
 
 	if (msg.m_nentries > 0)
@@ -5330,7 +5330,7 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
 			entry = hash->entries[i].entry;
 
 			entry->calls = 0;
-			INSTR_TIME_SET_ZERO(entry->times);
+			entry->times = 0;
 		}
 	}
 
@@ -5688,7 +5688,7 @@ pgstat_recv_waitaccum(PgStat_MsgWaitAccum *msg, int len)
 			 * Otherwise add the values to the existing entry.
 			 */
 			entry->calls += m_entry->calls;
-			INSTR_TIME_ADD(entry->times, m_entry->times);
+			entry->times += m_entry->times;
 		}
 	}
 }
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index 392a783fae..6d47eb0028 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -744,7 +744,7 @@ pgstat_report_waitaccum_start()
 
 	if (pgstat_track_wait_timing)
 	{
-		INSTR_TIME_SET_CURRENT(waitStart);
+		waitStart = rdtsc();
 	}
 }
 
@@ -752,15 +752,15 @@ static inline void
 pgstat_report_waitaccum_end()
 {
 	PgStat_WaitAccumEntry *entry;
-	instr_time  diff;
+	uint64		diff = 0;
 
 	if (wa_hash == NULL)
 		return;
 
 	if (pgstat_track_wait_timing)
 	{
-		INSTR_TIME_SET_CURRENT(diff);
-		INSTR_TIME_SUBTRACT(diff, waitStart);
+		diff = rdtsc();
+		diff -= waitStart;
 	}
 
 	entry = pgstat_get_wa_entry(wa_hash, *my_wait_event_info);
@@ -773,7 +773,7 @@ pgstat_report_waitaccum_end()
 	entry->calls++;
 	if (pgstat_track_wait_timing)
 	{
-		INSTR_TIME_ADD(entry->times, diff);
+		entry->times += diff;
 	}
 }
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 56afd20f22..6faedd4938 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2450,7 +2450,7 @@ pg_stat_get_waitaccum(PG_FUNCTION_ARGS)
 
 		values[2] = Int64GetDatum(entry->calls);
 
-		values[3] = UInt64GetDatum(INSTR_TIME_GET_MICROSEC(entry->times));
+		values[3] = UInt64GetDatum(entry->times);
 
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 	}
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 5564907df8..9a9ac8e16d 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -549,7 +549,7 @@ typedef struct PgStat_WaitAccumEntry
 {
 	uint32			wait_event_info;
 	PgStat_Counter	calls;
-	instr_time		times;
+	uint64			times;
 } PgStat_WaitAccumEntry;
 
 typedef struct WAEntry
@@ -978,7 +978,7 @@ typedef struct PgStat_FunctionCallUsage
 	instr_time	f_start;
 } PgStat_FunctionCallUsage;
 
-extern instr_time waitStart;
+extern uint64 waitStart;
 extern WAHash *wa_hash;
 
 /* ----------
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h
index 39a4f0600e..507a1ca44d 100644
--- a/src/include/portability/instr_time.h
+++ b/src/include/portability/instr_time.h
@@ -57,6 +57,10 @@
 
 #ifndef WIN32
 
+#if defined(__x86_64__) || defined(__i386__)
+#include <x86intrin.h>
+#endif
+
 #ifdef HAVE_CLOCK_GETTIME
 
 /* Use clock_gettime() */
@@ -209,6 +213,8 @@ typedef struct timeval instr_time;
 
 #else							/* WIN32 */
 
+#include <intrin.h>
+
 /* Use QueryPerformanceCounter() */
 
 typedef LARGE_INTEGER instr_time;
@@ -254,3 +260,18 @@ GetTimerFrequency(void)
 	(INSTR_TIME_IS_ZERO(t) ? INSTR_TIME_SET_CURRENT(t), true : false)
 
 #endif							/* INSTR_TIME_H */
+
+#ifndef RDTSC_H_
+#define RDTSC_H_
+
+static inline uint64 rdtsc() {
+	uint64 result;
+#if defined(__x86_64__) || defined(__i386__) || defined(WIN32)
+	result = __rdtsc();
+#else
+	result = 0;
+#endif
+	return result;
+}
+
+#endif
-- 
2.20.1

