aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2024-10-08 11:37:45 -0400
committerAndres Freund <andres@anarazel.de>2024-10-08 11:37:45 -0400
commit755a4c10d19dbe432a1860cced914c570ff3becc (patch)
tree7e803b760da946a32987cac5c2b0d21b5b9a9a32 /src/backend/storage/buffer/bufmgr.c
parent488f826c729bd570c36df369fa8ac90c9a5a1b46 (diff)
downloadpostgresql-755a4c10d19dbe432a1860cced914c570ff3becc.tar.gz
postgresql-755a4c10d19dbe432a1860cced914c570ff3becc.zip
bufmgr/smgr: Don't cross segment boundaries in StartReadBuffers()
With real AIO it doesn't make sense to cross segment boundaries with one IO. Add smgrmaxcombine() to allow upper layers to query which buffers can be merged. We could continue to cross segment boundaries when not using AIO, but it doesn't really make sense, because md.c will never be able to perform the read across the segment boundary in one system call. Which means we'll mark more buffers as undergoing IO than really makes sense - if another backend desires to read the same blocks, it'll be blocked longer than necessary. So it seems better to just never cross the boundary. Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Reviewed-by: Noah Misch <noah@leadboat.com> Discussion: https://postgr.es/m/1f6b50a7-38ef-4d87-8246-786d39f46ab9@iki.fi
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r--src/backend/storage/buffer/bufmgr.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index b8680cc8fd4..a19595865af 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1259,6 +1259,7 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
{
int actual_nblocks = *nblocks;
int io_buffers_len = 0;
+ int maxcombine = 0;
Assert(*nblocks > 0);
Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
@@ -1290,6 +1291,23 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
{
/* Extend the readable range to cover this block. */
io_buffers_len++;
+
+ /*
+ * Check how many blocks we can cover with the same IO. The smgr
+ * implementation might e.g. be limited due to a segment boundary.
+ */
+ if (i == 0 && actual_nblocks > 1)
+ {
+ maxcombine = smgrmaxcombine(operation->smgr,
+ operation->forknum,
+ blockNum);
+ if (unlikely(maxcombine < actual_nblocks))
+ {
+ elog(DEBUG2, "limiting nblocks at %u from %u to %u",
+ blockNum, actual_nblocks, maxcombine);
+ actual_nblocks = maxcombine;
+ }
+ }
}
}
*nblocks = actual_nblocks;