distance-tracking.txt
text/plain
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;
}