Skip to content

Commit aa1e8c2

Browse files
committed
Improve read_stream.c's fast path.
The "fast path" for well cached scans that don't do any I/O was accidentally coded in a way that could only be triggered by pg_prewarm's usage pattern, which starts out with a higher distance because of the flags it passes in. We want it to work for streaming sequential scans too, once that patch is committed. Adjust. Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGKXZALJ%3D6aArUsXRJzBm%3Dqvc4AWp7%3DiJNXJQqpbRLnD_w%40mail.gmail.com
1 parent 9e73869 commit aa1e8c2

File tree

1 file changed

+31
-44
lines changed

1 file changed

+31
-44
lines changed

src/backend/storage/aio/read_stream.c

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ get_per_buffer_data(ReadStream *stream, int16 buffer_index)
169169
/*
170170
* Ask the callback which block it would like us to read next, with a small
171171
* buffer in front to allow read_stream_unget_block() to work and to allow the
172-
* fast path to work in batches.
172+
* fast path to skip this function and work directly from the array.
173173
*/
174174
static inline BlockNumber
175175
read_stream_get_block(ReadStream *stream, void *per_buffer_data)
@@ -578,13 +578,12 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
578578
if (likely(stream->fast_path))
579579
{
580580
BlockNumber next_blocknum;
581-
bool need_wait;
582581

583582
/* Fast path assumptions. */
584583
Assert(stream->ios_in_progress == 0);
585584
Assert(stream->pinned_buffers == 1);
586585
Assert(stream->distance == 1);
587-
Assert(stream->pending_read_nblocks == 1);
586+
Assert(stream->pending_read_nblocks == 0);
588587
Assert(stream->per_buffer_data_size == 0);
589588

590589
/* We're going to return the buffer we pinned last time. */
@@ -594,58 +593,45 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
594593
buffer = stream->buffers[oldest_buffer_index];
595594
Assert(buffer != InvalidBuffer);
596595

597-
/*
598-
* Pin a buffer for the next call. Same buffer entry, and arbitrary
599-
* I/O entry (they're all free).
600-
*/
601-
need_wait = StartReadBuffer(&stream->ios[0].op,
602-
&stream->buffers[oldest_buffer_index],
603-
stream->pending_read_blocknum,
604-
stream->advice_enabled ?
605-
READ_BUFFERS_ISSUE_ADVICE : 0);
606-
607-
/* Choose the block the next call will pin. */
596+
/* Choose the next block to pin. */
608597
if (unlikely(stream->blocknums_next == stream->blocknums_count))
609598
read_stream_fill_blocknums(stream);
610599
next_blocknum = stream->blocknums[stream->blocknums_next++];
611600

612-
/*
613-
* Fast return if the next call doesn't require I/O for the buffer we
614-
* just pinned, and we have a block number to give it as a pending
615-
* read.
616-
*/
617-
if (likely(!need_wait && next_blocknum != InvalidBlockNumber))
601+
if (likely(next_blocknum != InvalidBlockNumber))
618602
{
619-
stream->pending_read_blocknum = next_blocknum;
620-
return buffer;
621-
}
622-
623-
/*
624-
* For anything more complex, set up some more state and take the slow
625-
* path next time.
626-
*/
627-
stream->fast_path = false;
603+
/*
604+
* Pin a buffer for the next call. Same buffer entry, and
605+
* arbitrary I/O entry (they're all free). We don't have to
606+
* adjust pinned_buffers because we're transferring one to caller
607+
* but pinning one more.
608+
*/
609+
if (likely(!StartReadBuffer(&stream->ios[0].op,
610+
&stream->buffers[oldest_buffer_index],
611+
next_blocknum,
612+
stream->advice_enabled ?
613+
READ_BUFFERS_ISSUE_ADVICE : 0)))
614+
{
615+
/* Fast return. */
616+
return buffer;
617+
}
628618

629-
if (need_wait)
630-
{
631619
/* Next call must wait for I/O for the newly pinned buffer. */
632620
stream->oldest_io_index = 0;
633621
stream->next_io_index = stream->max_ios > 1 ? 1 : 0;
634622
stream->ios_in_progress = 1;
635623
stream->ios[0].buffer_index = oldest_buffer_index;
636624
stream->seq_blocknum = next_blocknum + 1;
637625
}
638-
if (next_blocknum == InvalidBlockNumber)
639-
{
640-
/* Next call hits end of stream and can't pin anything more. */
641-
stream->distance = 0;
642-
stream->pending_read_nblocks = 0;
643-
}
644626
else
645627
{
646-
/* Set up the pending read. */
647-
stream->pending_read_blocknum = next_blocknum;
628+
/* No more blocks, end of stream. */
629+
stream->distance = 0;
630+
stream->oldest_buffer_index = stream->next_buffer_index;
631+
stream->pinned_buffers = 0;
648632
}
633+
634+
stream->fast_path = false;
649635
return buffer;
650636
}
651637
#endif
@@ -762,15 +748,11 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
762748
if (stream->ios_in_progress == 0 &&
763749
stream->pinned_buffers == 1 &&
764750
stream->distance == 1 &&
765-
stream->pending_read_nblocks == 1 &&
751+
stream->pending_read_nblocks == 0 &&
766752
stream->per_buffer_data_size == 0)
767753
{
768754
stream->fast_path = true;
769755
}
770-
else
771-
{
772-
stream->fast_path = false;
773-
}
774756
#endif
775757

776758
return buffer;
@@ -790,6 +772,11 @@ read_stream_reset(ReadStream *stream)
790772
/* Stop looking ahead. */
791773
stream->distance = 0;
792774

775+
/* Forget buffered block numbers and fast path state. */
776+
stream->blocknums_next = 0;
777+
stream->blocknums_count = 0;
778+
stream->fast_path = false;
779+
793780
/* Unpin anything that wasn't consumed. */
794781
while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
795782
ReleaseBuffer(buffer);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy