From 2eeec2f0488a74fa1f3cfdaeef36c5f9926d417c Mon Sep 17 00:00:00 2001 From: Thomas Munro 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)