v18-0001-Refactor-heap_page_prune_and_freeze-parameters-i.patch
text/x-patch
Filename: v18-0001-Refactor-heap_page_prune_and_freeze-parameters-i.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v18-0001
Subject: Refactor heap_page_prune_and_freeze() parameters into a struct
| File | + | − |
|---|---|---|
| src/backend/access/heap/pruneheap.c | 39 | 47 |
| src/backend/access/heap/vacuumlazy.c | 11 | 5 |
| src/include/access/heapam.h | 50 | 12 |
| src/tools/pgindent/typedefs.list | 1 | 0 |
From d385615495305be4d42aeee0422dfeef8d26f3a9 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Tue, 14 Oct 2025 11:10:25 -0400
Subject: [PATCH v18 01/12] Refactor heap_page_prune_and_freeze() parameters
into a struct
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
heap_page_prune_and_freeze() had accumulated an unwieldy number of input
parameters, and upcoming work to handle VM updates in this function will
add even more.
Introduce a new PruneFreezeParams struct to group the function’s input
parameters, improving readability and maintainability.
Discussion: https://postgr.es/m/yn4zp35kkdsjx6wf47zcfmxgexxt4h2og47pvnw2x5ifyrs3qc%407uw6jyyxuyf7
---
src/backend/access/heap/pruneheap.c | 86 +++++++++++++---------------
src/backend/access/heap/vacuumlazy.c | 16 ++++--
src/include/access/heapam.h | 62 ++++++++++++++++----
src/tools/pgindent/typedefs.list | 1 +
4 files changed, 101 insertions(+), 64 deletions(-)
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 231bea679c6..450b2eb6494 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -258,15 +258,23 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
{
OffsetNumber dummy_off_loc;
+ PruneFreezeParams params;
PruneFreezeResult presult;
+ params.relation = relation;
+ params.buffer = buffer;
+ params.reason = PRUNE_ON_ACCESS;
+ params.vistest = vistest;
+ params.cutoffs = NULL;
+
/*
* For now, pass mark_unused_now as false regardless of whether or
* not the relation has indexes, since we cannot safely determine
* that during on-access pruning with the current implementation.
*/
- heap_page_prune_and_freeze(relation, buffer, vistest, 0,
- NULL, &presult, PRUNE_ON_ACCESS, &dummy_off_loc, NULL, NULL);
+ params.options = 0;
+
+ heap_page_prune_and_freeze(¶ms, &presult, &dummy_off_loc, NULL, NULL);
/*
* Report the number of tuples reclaimed to pgstats. This is
@@ -419,60 +427,43 @@ heap_page_will_freeze(Relation relation, Buffer buffer,
* also need to account for a reduction in the length of the line pointer
* array following array truncation by us.
*
- * If the HEAP_PRUNE_FREEZE option is set, we will also freeze tuples if it's
- * required in order to advance relfrozenxid / relminmxid, or if it's
- * considered advantageous for overall system performance to do so now. The
- * 'cutoffs', 'presult', 'new_relfrozen_xid' and 'new_relmin_mxid' arguments
- * are required when freezing. When HEAP_PRUNE_FREEZE option is set, we also
- * set presult->all_visible and presult->all_frozen on exit, to indicate if
- * the VM bits can be set. They are always set to false when the
- * HEAP_PRUNE_FREEZE option is not set, because at the moment only callers
- * that also freeze need that information.
- *
- * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
- * (see heap_prune_satisfies_vacuum).
+ * params contains the input parameters used to control freezing and pruning
+ * behavior. See the definition of PruneFreezeParams for more on what each
+ * parameter does.
*
- * options:
- * MARK_UNUSED_NOW indicates that dead items can be set LP_UNUSED during
- * pruning.
- *
- * FREEZE indicates that we will also freeze tuples, and will return
- * 'all_visible', 'all_frozen' flags to the caller.
- *
- * cutoffs contains the freeze cutoffs, established by VACUUM at the beginning
- * of vacuuming the relation. Required if HEAP_PRUNE_FREEZE option is set.
- * cutoffs->OldestXmin is also used to determine if dead tuples are
- * HEAPTUPLE_RECENTLY_DEAD or HEAPTUPLE_DEAD.
+ * If the HEAP_PRUNE_FREEZE option is set in params, we will freeze tuples if
+ * it's required in order to advance relfrozenxid / relminmxid, or if it's
+ * considered advantageous for overall system performance to do so now. The
+ * 'params.cutoffs', 'presult', 'new_relfrozen_xid' and 'new_relmin_mxid'
+ * arguments are required when freezing. When HEAP_PRUNE_FREEZE option is
+ * passed, we also set presult->all_visible and presult->all_frozen on exit,
+ * to indicate if the VM bits can be set. They are always set to false when
+ * the HEAP_PRUNE_FREEZE option is not passed, because at the moment only
+ * callers that also freeze need that information.
*
* presult contains output parameters needed by callers, such as the number of
* tuples removed and the offsets of dead items on the page after pruning.
* heap_page_prune_and_freeze() is responsible for initializing it. Required
* by all callers.
*
- * reason indicates why the pruning is performed. It is included in the WAL
- * record for debugging and analysis purposes, but otherwise has no effect.
- *
* off_loc is the offset location required by the caller to use in error
* callback.
*
* new_relfrozen_xid and new_relmin_mxid must provided by the caller if the
- * HEAP_PRUNE_FREEZE option is set. On entry, they contain the oldest XID and
- * multi-XID seen on the relation so far. They will be updated with oldest
- * values present on the page after pruning. After processing the whole
- * relation, VACUUM can use these values as the new relfrozenxid/relminmxid
- * for the relation.
+ * HEAP_PRUNE_FREEZE option is set in params. On entry, they contain the
+ * oldest XID and multi-XID seen on the relation so far. They will be updated
+ * with oldest values present on the page after pruning. After processing the
+ * whole relation, VACUUM can use these values as the new
+ * relfrozenxid/relminmxid for the relation.
*/
void
-heap_page_prune_and_freeze(Relation relation, Buffer buffer,
- GlobalVisState *vistest,
- int options,
- struct VacuumCutoffs *cutoffs,
+heap_page_prune_and_freeze(PruneFreezeParams *params,
PruneFreezeResult *presult,
- PruneReason reason,
OffsetNumber *off_loc,
TransactionId *new_relfrozen_xid,
MultiXactId *new_relmin_mxid)
{
+ Buffer buffer = params->buffer;
Page page = BufferGetPage(buffer);
BlockNumber blockno = BufferGetBlockNumber(buffer);
OffsetNumber offnum,
@@ -486,10 +477,11 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
int64 fpi_before = pgWalUsage.wal_fpi;
/* Copy parameters to prstate */
- prstate.vistest = vistest;
- prstate.mark_unused_now = (options & HEAP_PAGE_PRUNE_MARK_UNUSED_NOW) != 0;
- prstate.attempt_freeze = (options & HEAP_PAGE_PRUNE_FREEZE) != 0;
- prstate.cutoffs = cutoffs;
+ prstate.vistest = params->vistest;
+ prstate.mark_unused_now =
+ (params->options & HEAP_PAGE_PRUNE_MARK_UNUSED_NOW) != 0;
+ prstate.attempt_freeze = (params->options & HEAP_PAGE_PRUNE_FREEZE) != 0;
+ prstate.cutoffs = params->cutoffs;
/*
* Our strategy is to scan the page and make lists of items to change,
@@ -583,7 +575,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
prstate.visibility_cutoff_xid = InvalidTransactionId;
maxoff = PageGetMaxOffsetNumber(page);
- tup.t_tableOid = RelationGetRelid(relation);
+ tup.t_tableOid = RelationGetRelid(params->relation);
/*
* Determine HTSV for all tuples, and queue them up for processing as HOT
@@ -786,7 +778,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
* Decide if we want to go ahead with freezing according to the freeze
* plans we prepared, or not.
*/
- do_freeze = heap_page_will_freeze(relation, buffer,
+ do_freeze = heap_page_will_freeze(params->relation, buffer,
did_tuple_hint_fpi,
do_prune,
do_hint_prune,
@@ -838,7 +830,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
/*
* Emit a WAL XLOG_HEAP2_PRUNE* record showing what we did
*/
- if (RelationNeedsWAL(relation))
+ if (RelationNeedsWAL(params->relation))
{
/*
* The snapshotConflictHorizon for the whole record should be the
@@ -876,11 +868,11 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
else
conflict_xid = prstate.latest_xid_removed;
- log_heap_prune_and_freeze(relation, buffer,
+ log_heap_prune_and_freeze(params->relation, buffer,
InvalidBuffer, /* vmbuffer */
0, /* vmflags */
conflict_xid,
- true, reason,
+ true, params->reason,
prstate.frozen, prstate.nfrozen,
prstate.redirected, prstate.nredirected,
prstate.nowdead, prstate.ndead,
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 71fbd68c8ea..7db7c56311b 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -1964,10 +1964,16 @@ lazy_scan_prune(LVRelState *vacrel,
{
Relation rel = vacrel->rel;
PruneFreezeResult presult;
- int prune_options = 0;
+ PruneFreezeParams params;
Assert(BufferGetBlockNumber(buf) == blkno);
+ params.relation = rel;
+ params.buffer = buf;
+ params.reason = PRUNE_VACUUM_SCAN;
+ params.cutoffs = &vacrel->cutoffs;
+ params.vistest = vacrel->vistest;
+
/*
* Prune all HOT-update chains and potentially freeze tuples on this page.
*
@@ -1983,12 +1989,12 @@ lazy_scan_prune(LVRelState *vacrel,
* tuples. Pruning will have determined whether or not the page is
* all-visible.
*/
- prune_options = HEAP_PAGE_PRUNE_FREEZE;
+ params.options = HEAP_PAGE_PRUNE_FREEZE;
if (vacrel->nindexes == 0)
- prune_options |= HEAP_PAGE_PRUNE_MARK_UNUSED_NOW;
+ params.options |= HEAP_PAGE_PRUNE_MARK_UNUSED_NOW;
- heap_page_prune_and_freeze(rel, buf, vacrel->vistest, prune_options,
- &vacrel->cutoffs, &presult, PRUNE_VACUUM_SCAN,
+ heap_page_prune_and_freeze(¶ms,
+ &presult,
&vacrel->offnum,
&vacrel->NewRelfrozenXid, &vacrel->NewRelminMxid);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 8cbff6ab0eb..74a5c24002b 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -221,6 +221,55 @@ typedef struct HeapPageFreeze
} HeapPageFreeze;
+
+/* 'reason' codes for heap_page_prune_and_freeze() */
+typedef enum
+{
+ PRUNE_ON_ACCESS, /* on-access pruning */
+ PRUNE_VACUUM_SCAN, /* VACUUM 1st heap pass */
+ PRUNE_VACUUM_CLEANUP, /* VACUUM 2nd heap pass */
+} PruneReason;
+
+/*
+ * Input parameters to heap_page_prune_and_freeze()
+ */
+typedef struct PruneFreezeParams
+{
+ Relation relation; /* relation containing buffer to be pruned */
+ Buffer buffer; /* buffer to be pruned */
+
+ /*
+ * The reason pruning was performed. It is used to set the WAL record
+ * opcode which is used for debugging and analysis purposes.
+ */
+ PruneReason reason;
+
+ /*
+ * Contains flag bits:
+ *
+ * MARK_UNUSED_NOW indicates that dead items can be set LP_UNUSED during
+ * pruning.
+ *
+ * FREEZE indicates that we will also freeze tuples, and will return
+ * 'all_visible', 'all_frozen' flags to the caller.
+ */
+ int options;
+
+ /*
+ * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
+ * (see heap_prune_satisfies_vacuum).
+ */
+ GlobalVisState *vistest;
+
+ /*
+ * cutoffs contains the freeze cutoffs, established by VACUUM at the
+ * beginning of vacuuming the relation. Required if HEAP_PRUNE_FREEZE
+ * option is set. cutoffs->OldestXmin is also used to determine if dead
+ * tuples are HEAPTUPLE_RECENTLY_DEAD or HEAPTUPLE_DEAD.
+ */
+ struct VacuumCutoffs *cutoffs;
+} PruneFreezeParams;
+
/*
* Per-page state returned by heap_page_prune_and_freeze()
*/
@@ -264,13 +313,6 @@ typedef struct PruneFreezeResult
OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
} PruneFreezeResult;
-/* 'reason' codes for heap_page_prune_and_freeze() */
-typedef enum
-{
- PRUNE_ON_ACCESS, /* on-access pruning */
- PRUNE_VACUUM_SCAN, /* VACUUM 1st heap pass */
- PRUNE_VACUUM_CLEANUP, /* VACUUM 2nd heap pass */
-} PruneReason;
/* ----------------
* function prototypes for heap access method
@@ -367,12 +409,8 @@ extern TransactionId heap_index_delete_tuples(Relation rel,
/* in heap/pruneheap.c */
extern void heap_page_prune_opt(Relation relation, Buffer buffer);
-extern void heap_page_prune_and_freeze(Relation relation, Buffer buffer,
- GlobalVisState *vistest,
- int options,
- struct VacuumCutoffs *cutoffs,
+extern void heap_page_prune_and_freeze(PruneFreezeParams *params,
PruneFreezeResult *presult,
- PruneReason reason,
OffsetNumber *off_loc,
TransactionId *new_relfrozen_xid,
MultiXactId *new_relmin_mxid);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 5290b91e83e..b221b3699bf 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2342,6 +2342,7 @@ ProjectionPath
PromptInterruptContext
ProtocolVersion
PrsStorage
+PruneFreezeParams
PruneFreezeResult
PruneReason
PruneState
--
2.43.0