0003-aio-Improve-read_stream.c-look-ahead-heuristics-A.txt
text/plain
Filename: 0003-aio-Improve-read_stream.c-look-ahead-heuristics-A.txt
Type: text/plain
Part: 2
Message:
Re: index prefetching
From 7e862c651a9b023bc9b3363f59d17b8bc6a22089 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 21 Jul 2025 16:34:59 +1200
Subject: [PATCH 3/3] aio: Improve read_stream.c look-ahead heuristics A.
Previously we would reduce the look-ahead distance by one every time we
got a cache hit, which sometimes performed poorly with mixed hit/miss
patterns, especially if it was trapped at one.
The new rule prevents distance reduction while any IO is still running,
which allows for more concurrent I/O with some mixed hit/miss patterns
that the old algorithm didn't handle well.
XXX But you can always adjust
your test patterns with more hit between the misses to make it give up
I/O concurrency that you could have benefited from....
XXX But it also finds it way back to the fast path sooner...
XXX Highly experimental!
Suggested-by: AF
---
src/backend/storage/aio/read_stream.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index f242b373b22..8961fad463f 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -343,22 +343,25 @@ read_stream_start_pending_read(ReadStream *stream)
/* Remember whether we need to wait before returning this buffer. */
if (!need_wait)
{
- /* Look-ahead distance decays, no I/O necessary. */
- if (stream->distance > 1)
+ /* Look-ahead distance decays when there is no I/O activity. */
+ if (stream->distance > 1 && stream->ios_in_progress == 0)
stream->distance--;
}
else
{
- /*
- * Remember to call WaitReadBuffers() before returning head buffer.
- * Look-ahead distance will be adjusted after waiting.
- */
+ /* Remember to call WaitReadBuffers() before returning head buffer. */
stream->ios[io_index].buffer_index = buffer_index;
if (++stream->next_io_index == stream->max_ios)
stream->next_io_index = 0;
Assert(stream->ios_in_progress < stream->max_ios);
stream->ios_in_progress++;
stream->seq_blocknum = stream->pending_read_blocknum + nblocks;
+
+ /* Look-ahead distance grows by twice this read size. */
+ if (stream->max_pinned_buffers - stream->distance < nblocks * 2)
+ stream->distance = stream->max_pinned_buffers;
+ else
+ stream->distance += nblocks * 2;
}
/*
@@ -897,7 +900,6 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
stream->ios[stream->oldest_io_index].buffer_index == oldest_buffer_index)
{
int16 io_index = stream->oldest_io_index;
- int32 distance; /* wider temporary value, clamped below */
/* Sanity check that we still agree on the buffers. */
Assert(stream->ios[io_index].op.buffers ==
@@ -910,11 +912,6 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
if (++stream->oldest_io_index == stream->max_ios)
stream->oldest_io_index = 0;
- /* Look-ahead distance ramps up rapidly after we do I/O. */
- distance = stream->distance * 2;
- distance = Min(distance, stream->max_pinned_buffers);
- stream->distance = distance;
-
/*
* If we've reached the first block of a sequential region we're
* issuing advice for, cancel that until the next jump. The kernel
--
2.39.5 (Apple Git-154)