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; }