From 7367cce118e5196b7e916c1d8e8403198c5334a5 Mon Sep 17 00:00:00 2001 From: Michael Zhilin Date: Sun, 30 Mar 2025 01:30:37 +0300 Subject: [PATCH v1] Avoid useless prefetches in case of recent FPI WAL records If block is logged into WAL with full page, then the startup process reads full page image from WAL stream and load them into shared buffer by XLogReadBufferForRedoExtended. Every further WAL records related to particular blocks should be skipped by XLogPrefetcher. --- src/backend/access/transam/xlogprefetcher.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c index 7735562db01..3378b72fd96 100644 --- a/src/backend/access/transam/xlogprefetcher.c +++ b/src/backend/access/transam/xlogprefetcher.c @@ -51,7 +51,7 @@ /* * To detect repeated access to the same block and skip useless extra system - * calls, we remember a small window of recently prefetched blocks. + * calls, we remember a small window of recently prefetched / FPW blocks. */ #define XLOGPREFETCHER_SEQ_WINDOW_SIZE 4 @@ -674,6 +674,25 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn) if (block->has_image) { XLogPrefetchIncrement(&SharedStats->skip_fpw); + /* + * A full page image is copied to shared buffer during replay. + * Every next WAL records related to particular block doesn't + * require prefetching of shared buffer. + */ + for (int i = 0; i < XLOGPREFETCHER_SEQ_WINDOW_SIZE; ++i) + { + if (block->blkno == prefetcher->recent_block[i] && + RelFileLocatorEquals(block->rlocator, prefetcher->recent_rlocator[i])) + { + return LRQ_NEXT_NO_IO; + } + } + + prefetcher->recent_rlocator[prefetcher->recent_idx] = block->rlocator; + prefetcher->recent_block[prefetcher->recent_idx] = block->blkno; + prefetcher->recent_idx = + (prefetcher->recent_idx + 1) % XLOGPREFETCHER_SEQ_WINDOW_SIZE; + return LRQ_NEXT_NO_IO; } -- 2.49.0