0001-Add-AutoReadStream.txt
text/plain
From 2eeec2f0488a74fa1f3cfdaeef36c5f9926d417c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 12 Oct 2024 09:57:01 +1300
Subject: [PATCH 1/2] Add AutoReadStream.
Provide auto_read_buffer() as a drop-in replacement for ReadBuffer().
As long as the caller requests sequential pages, they come from a
ReadStream that predicts that it'll keep doing that. Otherwise it falls
back to regular ReadBuffer().
XXX experimental
---
src/backend/storage/aio/Makefile | 1 +
src/backend/storage/aio/auto_read_stream.c | 92 ++++++++++++++++++++++
src/backend/storage/aio/meson.build | 1 +
src/include/storage/auto_read_stream.h | 16 ++++
src/tools/pgindent/typedefs.list | 1 +
5 files changed, 111 insertions(+)
create mode 100644 src/backend/storage/aio/auto_read_stream.c
create mode 100644 src/include/storage/auto_read_stream.h
diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile
index 3f2469cc399..7270f486109 100644
--- a/src/backend/storage/aio/Makefile
+++ b/src/backend/storage/aio/Makefile
@@ -15,6 +15,7 @@ OBJS = \
aio_init.o \
aio_io.o \
aio_target.o \
+ auto_read_stream.o \
method_io_uring.o \
method_sync.o \
method_worker.o \
diff --git a/src/backend/storage/aio/auto_read_stream.c b/src/backend/storage/aio/auto_read_stream.c
new file mode 100644
index 00000000000..a8dac066bd6
--- /dev/null
+++ b/src/backend/storage/aio/auto_read_stream.c
@@ -0,0 +1,92 @@
+#include "postgres.h"
+#include "storage/auto_read_stream.h"
+#include "storage/bufmgr.h"
+#include "storage/read_stream.h"
+
+struct AutoReadStream
+{
+ ReadStream *stream;
+ Relation rel;
+ BlockNumber next;
+ BlockNumber last;
+};
+
+static BlockNumber
+auto_read_stream_cb(ReadStream *stream,
+ void *callback_private_data,
+ void *per_buffer_data)
+{
+ AutoReadStream *auto_stream = callback_private_data;
+ BlockNumber next = auto_stream->next;
+
+ if (next == InvalidBlockNumber)
+ return InvalidBuffer;
+ auto_stream->next = Min(auto_stream->next + 1, auto_stream->last);
+
+ return next;
+}
+
+AutoReadStream *
+auto_read_stream_begin(BufferAccessStrategy strategy,
+ Relation rel,
+ ForkNumber forknum)
+{
+ AutoReadStream *auto_stream;
+
+ auto_stream = palloc(sizeof(*auto_stream));
+ auto_stream->rel = rel;
+ auto_stream->next = InvalidBlockNumber;
+ auto_stream->last = InvalidBlockNumber;
+ auto_stream->stream = read_stream_begin_relation(0,
+ strategy,
+ rel,
+ forknum,
+ auto_read_stream_cb,
+ auto_stream,
+ 0);
+
+ return auto_stream;
+}
+
+void
+auto_read_stream_end(AutoReadStream *auto_stream)
+{
+ read_stream_end(auto_stream->stream);
+ pfree(auto_stream);
+}
+
+Buffer
+auto_read_buffer(AutoReadStream *auto_stream, BlockNumber blocknum)
+{
+
+ if (auto_stream->last != InvalidBlockNumber)
+ {
+ Buffer buffer = read_stream_next_buffer(auto_stream->stream, NULL);
+
+ /* Did the stream guess right? */
+ if (buffer != InvalidBlockNumber)
+ {
+ if (BufferGetBlockNumber(buffer) == blocknum)
+ return buffer;
+ ReleaseBuffer(buffer);
+ }
+ }
+
+ /* Figure out the highest block number if we haven't already. */
+ if (auto_stream->last == InvalidBlockNumber)
+ {
+ BlockNumber nblocks;
+
+ nblocks = RelationGetNumberOfBlocks(auto_stream->rel);
+ if (nblocks > 0)
+ auto_stream->last = nblocks - 1;
+ }
+
+ /* Take a guess at the next block. */
+ if (auto_stream->last != InvalidBlockNumber &&
+ auto_stream->last >= blocknum + 1)
+ auto_stream->next = blocknum + 1;
+ read_stream_reset(auto_stream->stream);
+
+ return ReadBuffer(auto_stream->rel, blocknum);
+}
diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build
index da6df2d3654..07c2fb2e42c 100644
--- a/src/backend/storage/aio/meson.build
+++ b/src/backend/storage/aio/meson.build
@@ -7,6 +7,7 @@ backend_sources += files(
'aio_init.c',
'aio_io.c',
'aio_target.c',
+ 'auto_read_stream.c',
'method_io_uring.c',
'method_sync.c',
'method_worker.c',
diff --git a/src/include/storage/auto_read_stream.h b/src/include/storage/auto_read_stream.h
new file mode 100644
index 00000000000..96d4a9ac726
--- /dev/null
+++ b/src/include/storage/auto_read_stream.h
@@ -0,0 +1,16 @@
+#ifndef AUTO_READ_STREAM_H
+#define AUTO_READ_STREAM_H
+
+#include "storage/bufmgr.h"
+
+struct AutoReadStream;
+typedef struct AutoReadStream AutoReadStream;
+
+extern AutoReadStream *auto_read_stream_begin(BufferAccessStrategy strategy,
+ Relation rel,
+ ForkNumber forknum);
+extern void auto_read_stream_end(AutoReadStream *auto_stream);
+extern Buffer auto_read_buffer(AutoReadStream *auto_stream,
+ BlockNumber blocknum);
+
+#endif
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index e6f2e93b2d6..43f206e30ed 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -173,6 +173,7 @@ AuthRequest
AuthToken
AutoPrewarmReadStreamData
AutoPrewarmSharedState
+AutoReadStream
AutoVacOpts
AutoVacuumShmemStruct
AutoVacuumWorkItem
--
2.39.5 (Apple Git-154)