Provide multi-block smgrprefetch().
authorThomas Munro <tmunro@postgresql.org>
Sat, 16 Dec 2023 03:14:47 +0000 (16:14 +1300)
committerThomas Munro <tmunro@postgresql.org>
Sat, 16 Dec 2023 04:51:21 +0000 (17:51 +1300)
Previously smgrprefetch() could issue POSIX_FADV_WILLNEED advice for a
single block at a time.  Add an nblocks argument so that we can do the
same for a range of blocks.  This usually produces a single system call,
but might need to loop if it crosses a segment boundary.  Initially it
is only called with nblocks == 1, but proposed patches will make wider
calls.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> (earlier version)
Discussion: https://postgr.es/m/CA+hUKGJkOiOCa+mag4BF+zHo7qo=o9CFheB8=g6uT5TUm2gkvA@mail.gmail.com

src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/backend/storage/smgr/md.c
src/backend/storage/smgr/smgr.c
src/include/storage/md.h
src/include/storage/smgr.h

index f7c67d504cd038a9607de02625536a02488258db..de8b5edbfbfbeb8f5b9304cd79ba646e940b33cd 100644 (file)
@@ -569,7 +569,7 @@ PrefetchSharedBuffer(SMgrRelation smgr_reln,
                 * recovery if the relation file doesn't exist.
                 */
                if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
-                       smgrprefetch(smgr_reln, forkNum, blockNum))
+                       smgrprefetch(smgr_reln, forkNum, blockNum, 1))
                {
                        result.initiated_io = true;
                }
index aebcf146b451feb1c21f86bda14270a89d3c4c54..c75ed184e04434be04b61329c05a968be14ab124 100644 (file)
@@ -94,7 +94,7 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
 #ifdef USE_PREFETCH
                /* Not in buffers, so initiate prefetch */
                if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
-                       smgrprefetch(smgr, forkNum, blockNum))
+                       smgrprefetch(smgr, forkNum, blockNum, 1))
                {
                        result.initiated_io = true;
                }
index fdecbad17095743c1b0e178d3a6dbd98aa6817fd..091993ea45b6e72596c96a00ed796b30abcc45a1 100644 (file)
@@ -710,27 +710,44 @@ mdclose(SMgrRelation reln, ForkNumber forknum)
 }
 
 /*
- * mdprefetch() -- Initiate asynchronous read of the specified block of a relation
+ * mdprefetch() -- Initiate asynchronous read of the specified blocks of a relation
  */
 bool
-mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
+mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                  int nblocks)
 {
 #ifdef USE_PREFETCH
-       off_t           seekpos;
-       MdfdVec    *v;
 
        Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
 
-       v = _mdfd_getseg(reln, forknum, blocknum, false,
-                                        InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
-       if (v == NULL)
+       if ((uint64) blocknum + nblocks > (uint64) MaxBlockNumber + 1)
                return false;
 
-       seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
+       while (nblocks > 0)
+       {
+               off_t           seekpos;
+               MdfdVec    *v;
+               int                     nblocks_this_segment;
 
-       Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
+               v = _mdfd_getseg(reln, forknum, blocknum, false,
+                                                InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
+               if (v == NULL)
+                       return false;
+
+               seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
 
-       (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
+               Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
+
+               nblocks_this_segment =
+                       Min(nblocks,
+                               RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
+
+               (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ * nblocks_this_segment,
+                                                       WAIT_EVENT_DATA_FILE_PREFETCH);
+
+               blocknum += nblocks_this_segment;
+               nblocks -= nblocks_this_segment;
+       }
 #endif                                                 /* USE_PREFETCH */
 
        return true;
index 4c552649336ee92157c34b629de7bba4557b6447..003a55a592c29b9e85cb5e4a364dad6f7a292b6e 100644 (file)
@@ -54,7 +54,7 @@ typedef struct f_smgr
        void            (*smgr_zeroextend) (SMgrRelation reln, ForkNumber forknum,
                                                                        BlockNumber blocknum, int nblocks, bool skipFsync);
        bool            (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
-                                                                 BlockNumber blocknum);
+                                                                 BlockNumber blocknum, int nblocks);
        void            (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
                                                          BlockNumber blocknum, void *buffer);
        void            (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
@@ -547,9 +547,10 @@ smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
  * record).
  */
 bool
-smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
+smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+                        int nblocks)
 {
-       return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
+       return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum, nblocks);
 }
 
 /*
index 941879ee6a8fda631cea27f07f8a40601fce501f..091784c171e353b268e487ad73431527fd8970df 100644 (file)
@@ -31,7 +31,7 @@ extern void mdextend(SMgrRelation reln, ForkNumber forknum,
 extern void mdzeroextend(SMgrRelation reln, ForkNumber forknum,
                                                 BlockNumber blocknum, int nblocks, bool skipFsync);
 extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum,
-                                          BlockNumber blocknum);
+                                          BlockNumber blocknum, int nblocks);
 extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
                                   void *buffer);
 extern void mdwrite(SMgrRelation reln, ForkNumber forknum,
index a9a179aabacc488b7bd5d1e9de88c05df3891c3a..da7e7c5a2e6a97b28b4610a699ee86a6f7b75ad8 100644 (file)
@@ -95,7 +95,7 @@ extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
 extern void smgrzeroextend(SMgrRelation reln, ForkNumber forknum,
                                                   BlockNumber blocknum, int nblocks, bool skipFsync);
 extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
-                                                BlockNumber blocknum);
+                                                BlockNumber blocknum, int nblocks);
 extern void smgrread(SMgrRelation reln, ForkNumber forknum,
                                         BlockNumber blocknum, void *buffer);
 extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,