From 18eea37d9f5d46d2e2c1295528de2154ed23456d Mon Sep 17 00:00:00 2001 From: Matthias van de Meent 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)