From a00a528be26b06d7de40d59381b7ee864f06f3a9 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 26 Mar 2020 22:34:29 +1300 Subject: [PATCH v6 6/8] Add ReadBufferPrefetched() (POC only) Provide a potentially faster version of ReadBuffer(), or cases where you have a PrefetchBufferResult. We might be able to avoid an extra buffer mapping table lookup. NOT FOR COMMIT -- PROOF OF CONCEPT ONLY --- src/backend/storage/buffer/bufmgr.c | 49 +++++++++++++++++++++++++++++ src/include/storage/bufmgr.h | 3 ++ 2 files changed, 52 insertions(+) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 23f269ae74..f00c837f5a 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -597,6 +597,55 @@ PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum) } } +/* + * ReadBufferPrefetched -- read a buffer for which a prefetch was issued + * + * Like ReadBuffer(), but try to use the result of a recent PrefetchBuffer() + * call to avoid a buffer mapping table lookup. + */ +Buffer +ReadBufferPrefetched(PrefetchBufferResult *prefetch, + Relation reln, + BlockNumber blockNum) +{ + /* + * If PrefetchBuffer() found this block in a buffer recently, try to pin it + * and then double check that it still holds the block we want. + */ + if (BufferIsValid(prefetch->recent_buffer)) + { + BufferDesc *bufHdr; + BufferTag tag; + + if (BufferIsLocal(prefetch->recent_buffer)) + { + bufHdr = GetBufferDescriptor(-prefetch->recent_buffer - 1); + } + else + { + bufHdr = GetBufferDescriptor(prefetch->recent_buffer - 1); + ResourceOwnerEnlargeBuffers(CurrentResourceOwner); + if (!PinBuffer(bufHdr, NULL)) + { + /* not valid, forget about it */ + UnpinBuffer(bufHdr, true); + bufHdr = NULL; + } + } + + /* If we managed to pin it or it's local, check tag. */ + if (bufHdr) + { + RelationOpenSmgr(reln); + INIT_BUFFERTAG(tag, reln->rd_smgr->smgr_rnode.node, MAIN_FORKNUM, + blockNum); + if (BUFFERTAGS_EQUAL(tag, bufHdr->tag)) + return BufferDescriptorGetBuffer(bufHdr); + } + } + + return ReadBuffer(reln, blockNum); +} /* * ReadBuffer -- a shorthand for ReadBufferExtended, for reading from main diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index ee91b8fa26..8f6b19e6ac 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -183,6 +183,9 @@ extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy); +extern Buffer ReadBufferPrefetched(PrefetchBufferResult *prefetch, + Relation reln, + BlockNumber blockNum); extern void ReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer); extern void MarkBufferDirty(Buffer buffer); -- 2.20.1