distance-tracking.txt

text/plain

Filename: distance-tracking.txt
Type: text/plain
Part: 0
Message: Re: index prefetching
diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
index 0e618f66ae..7fd5cdfc43 100644
--- a/contrib/pg_buffercache/Makefile
+++ b/contrib/pg_buffercache/Makefile
@@ -9,7 +9,8 @@ EXTENSION = pg_buffercache
 DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \
 	pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \
 	pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql \
-	pg_buffercache--1.5--1.6.sql pg_buffercache--1.6--1.7.sql
+	pg_buffercache--1.5--1.6.sql pg_buffercache--1.6--1.7.sql \
+	pg_buffercache--1.7--1.8.sql
 PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
 
 REGRESS = pg_buffercache pg_buffercache_numa
diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
index 1149955094..d2fa8ba53b 100644
--- a/contrib/pg_buffercache/pg_buffercache.control
+++ b/contrib/pg_buffercache/pg_buffercache.control
@@ -1,5 +1,5 @@
 # pg_buffercache extension
 comment = 'examine the shared buffer cache'
-default_version = '1.7'
+default_version = '1.8'
 module_pathname = '$libdir/pg_buffercache'
 relocatable = true
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 89b8685524..d758d0c855 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -107,6 +107,8 @@ PG_FUNCTION_INFO_V1(pg_buffercache_evict_all);
 PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty);
 PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty_relation);
 PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty_all);
+PG_FUNCTION_INFO_V1(pg_set_prefetch_tracking);
+PG_FUNCTION_INFO_V1(pg_prefetch_distance);
 
 
 /* Only need to touch memory once per backend process lifetime */
@@ -958,3 +960,23 @@ pg_buffercache_mark_dirty_all(PG_FUNCTION_ARGS)
 
 	PG_RETURN_DATUM(result);
 }
+
+/* Prefetch distance tracking - calls into read_stream.c */
+extern void pg_set_distance_tracking(Oid relid);
+extern int16 pg_pop_prefetch_distance(void);
+
+Datum
+pg_set_prefetch_tracking(PG_FUNCTION_ARGS)
+{
+	pg_set_distance_tracking(PG_GETARG_OID(0));
+	PG_RETURN_VOID();
+}
+
+Datum
+pg_prefetch_distance(PG_FUNCTION_ARGS)
+{
+	int16 r = pg_pop_prefetch_distance();
+	if (r < 0)
+		PG_RETURN_NULL();
+	PG_RETURN_INT32((int32) r);
+}
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 7d619d2171..b0177417e0 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -80,6 +80,47 @@
 #include "utils/rel.h"
 #include "utils/spccache.h"
 
+/* Per-tuple prefetch distance tracking (for debugging/analysis) */
+#define DISTANCE_QUEUE_SIZE 16384
+static int16 distance_queue[DISTANCE_QUEUE_SIZE];
+static int dq_head, dq_tail, dq_count;
+static Oid tracked_relid = InvalidOid;
+
+PGDLLEXPORT void
+pg_set_distance_tracking(Oid relid)
+{
+	tracked_relid = relid;
+	dq_head = dq_tail = dq_count = 0;
+}
+
+PGDLLEXPORT int16
+pg_pop_prefetch_distance(void)
+{
+	int16 r;
+
+	if (dq_count == 0)
+		return -1;
+	r = distance_queue[dq_tail];
+	dq_tail = (dq_tail + 1) % DISTANCE_QUEUE_SIZE;
+	dq_count--;
+	return r;
+}
+
+static void
+push_distance(Oid relid, int16 distance)
+{
+	if (relid != tracked_relid)
+		return;
+	if (dq_count >= DISTANCE_QUEUE_SIZE)
+	{
+		dq_tail = (dq_tail + 1) % DISTANCE_QUEUE_SIZE;
+		dq_count--;
+	}
+	distance_queue[dq_head] = distance;
+	dq_head = (dq_head + 1) % DISTANCE_QUEUE_SIZE;
+	dq_count++;
+}
+
 typedef struct InProgressIO
 {
 	int16		buffer_index;
@@ -107,6 +148,7 @@ struct ReadStream
 	bool		advice_enabled;
 	bool		temporary;
 	bool		yielded;
+	Oid			relid;			/* for distance tracking */
 
 	/*
 	 * One-block buffer to support 'ungetting' a block number, to resolve flow
@@ -703,6 +745,7 @@ read_stream_begin_impl(int flags,
 	stream->seq_blocknum = InvalidBlockNumber;
 	stream->seq_until_processed = InvalidBlockNumber;
 	stream->temporary = SmgrIsTemp(smgr);
+	stream->relid = rel ? RelationGetRelid(rel) : InvalidOid;
 
 	/*
 	 * Skip the initial ramp-up phase if the caller says we're going to be
@@ -851,6 +894,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 										flags)))
 			{
 				/* Fast return. */
+				push_distance(stream->relid, stream->distance);
 				return buffer;
 			}
 
@@ -871,6 +915,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 		}
 
 		stream->fast_path = false;
+		push_distance(stream->relid, stream->distance);
 		return buffer;
 	}
 #endif
@@ -1027,6 +1072,9 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
 	}
 #endif
 
+	/* Push distance for per-tuple tracking */
+	push_distance(stream->relid, stream->distance);
+
 	return buffer;
 }