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