v13-0002-pg_visibility-vectorize-collect_visibility_data.patch
application/octet-stream
Filename: v13-0002-pg_visibility-vectorize-collect_visibility_data.patch
Type: application/octet-stream
Part: 7
From 18eea37d9f5d46d2e2c1295528de2154ed23456d Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Fri, 19 Dec 2025 22:27:04 +0100
Subject: [PATCH v13 2/8] pg_visibility: vectorize collect_visibility_data
---
contrib/pg_visibility/pg_visibility.c | 40 +++++++++++++++++++++------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 7046c1b5f8e..8c76b0bf7f6 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -510,6 +510,9 @@ collect_visibility_data(Oid relid, bool include_pd)
BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
BlockRangeReadStreamPrivate p;
ReadStream *stream = NULL;
+#define VM_BATCHSIZE 1024
+ BlockNumber *blknos;
+ uint8 *status;
rel = relation_open(relid, AccessShareLock);
@@ -521,6 +524,9 @@ collect_visibility_data(Oid relid, bool include_pd)
info->next = 0;
info->count = nblocks;
+ blknos = palloc0_array(BlockNumber, VM_BATCHSIZE);
+ status = palloc0_array(uint8, VM_BATCHSIZE);
+
/* Create a stream if reading main fork. */
if (include_pd)
{
@@ -541,30 +547,44 @@ collect_visibility_data(Oid relid, bool include_pd)
0);
}
- for (blkno = 0; blkno < nblocks; ++blkno)
+ for (blkno = 0; blkno < nblocks;)
{
- int32 mapbits;
+ int batchsize = 0;
+
+ for (BlockNumber bno = blkno; batchsize < VM_BATCHSIZE && bno < nblocks;)
+ blknos[batchsize++] = bno++;
/* Make sure we are interruptible. */
CHECK_FOR_INTERRUPTS();
- /* Get map info. */
- mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
- if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
- info->bits[blkno] |= (1 << 0);
- if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
- info->bits[blkno] |= (1 << 1);
+ /* Get map info in bulk. */
+ visibilitymap_get_statusv(rel, blknos, status, batchsize, &vmbuffer);
+
+ /* move the status bits */
+ for (int i = 0; i < batchsize; i++)
+ {
+ uint32 mapbits = status[i];
+ BlockNumber bno = blknos[i];
+
+ if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
+ info->bits[bno] |= (1 << 0);
+ if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
+ info->bits[bno] |= (1 << 1);
+ }
/*
* Page-level data requires reading every block, so only get it if the
* caller needs it. Use a buffer access strategy, too, to prevent
* cache-trashing.
*/
- if (include_pd)
+ for (int i = 0; include_pd && i < batchsize; i++)
{
Buffer buffer;
Page page;
+ /* This subloop should be interruptable, it does IO */
+ CHECK_FOR_INTERRUPTS();
+
buffer = read_stream_next_buffer(stream, NULL);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
@@ -574,6 +594,8 @@ collect_visibility_data(Oid relid, bool include_pd)
UnlockReleaseBuffer(buffer);
}
+
+ blkno += batchsize;
}
if (include_pd)
--
2.50.1 (Apple Git-155)