Skip to content

Commit 9917e79

Browse files
committed
Minor refactoring in heap_page_prune
Pass 'page', 'blockno' and 'maxoff' to heap_prune_chain() as arguments, so that it doesn't need to fetch them from the buffer. This saves a few cycles per chain. Remove the "if (off_loc != NULL)" checks, and require the caller to pass a non-NULL 'off_loc'. Pass a pointer to a dummy local variable when it's not needed. Those checks are cheap, but it's still better to avoid them in the per-chain loops when we can do so easily. The CPU time saving from these changes are hardly measurable, but fewer instructions is good anyway, so why not. I spotted the potential for these while reviewing Melanie Plageman's patch set to combine prune and freeze records. Discussion: https://www.postgresql.org/message-id/CAAKRu_abm2tHhrc0QSQa%3D%3DsHe%3DVA1%3Doz1dJMQYUOKuHmu%2B9Xrg%40mail.gmail.com
1 parent f5a2278 commit 9917e79

File tree

1 file changed

+15
-22
lines changed

1 file changed

+15
-22
lines changed

src/backend/access/heap/pruneheap.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@ typedef struct
5757
static HTSV_Result heap_prune_satisfies_vacuum(PruneState *prstate,
5858
HeapTuple tup,
5959
Buffer buffer);
60-
static int heap_prune_chain(Buffer buffer,
61-
OffsetNumber rootoffnum,
62-
int8 *htsv,
63-
PruneState *prstate);
60+
static int heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
61+
OffsetNumber rootoffnum, int8 *htsv, PruneState *prstate);
6462
static void heap_prune_record_prunable(PruneState *prstate, TransactionId xid);
6563
static void heap_prune_record_redirect(PruneState *prstate,
6664
OffsetNumber offnum, OffsetNumber rdoffnum);
@@ -145,6 +143,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
145143
*/
146144
if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
147145
{
146+
OffsetNumber dummy_off_loc;
148147
PruneResult presult;
149148

150149
/*
@@ -153,7 +152,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
153152
* that during on-access pruning with the current implementation.
154153
*/
155154
heap_page_prune(relation, buffer, vistest, false,
156-
&presult, PRUNE_ON_ACCESS, NULL);
155+
&presult, PRUNE_ON_ACCESS, &dummy_off_loc);
157156

158157
/*
159158
* Report the number of tuples reclaimed to pgstats. This is
@@ -296,8 +295,7 @@ heap_page_prune(Relation relation, Buffer buffer,
296295
* Set the offset number so that we can display it along with any
297296
* error that occurred while processing this tuple.
298297
*/
299-
if (off_loc)
300-
*off_loc = offnum;
298+
*off_loc = offnum;
301299

302300
presult->htsv[offnum] = heap_prune_satisfies_vacuum(&prstate, &tup,
303301
buffer);
@@ -315,22 +313,20 @@ heap_page_prune(Relation relation, Buffer buffer,
315313
continue;
316314

317315
/* see preceding loop */
318-
if (off_loc)
319-
*off_loc = offnum;
316+
*off_loc = offnum;
320317

321318
/* Nothing to do if slot is empty */
322319
itemid = PageGetItemId(page, offnum);
323320
if (!ItemIdIsUsed(itemid))
324321
continue;
325322

326323
/* Process this item or chain of items */
327-
presult->ndeleted += heap_prune_chain(buffer, offnum,
324+
presult->ndeleted += heap_prune_chain(page, blockno, maxoff, offnum,
328325
presult->htsv, &prstate);
329326
}
330327

331328
/* Clear the offset information once we have processed the given page. */
332-
if (off_loc)
333-
*off_loc = InvalidOffsetNumber;
329+
*off_loc = InvalidOffsetNumber;
334330

335331
/* Any error while applying the changes is critical */
336332
START_CRIT_SECTION();
@@ -452,30 +448,28 @@ heap_prune_satisfies_vacuum(PruneState *prstate, HeapTuple tup, Buffer buffer)
452448
* Returns the number of tuples (to be) deleted from the page.
453449
*/
454450
static int
455-
heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum,
456-
int8 *htsv, PruneState *prstate)
451+
heap_prune_chain(Page page, BlockNumber blockno, OffsetNumber maxoff,
452+
OffsetNumber rootoffnum, int8 *htsv, PruneState *prstate)
457453
{
458454
int ndeleted = 0;
459-
Page dp = (Page) BufferGetPage(buffer);
460455
TransactionId priorXmax = InvalidTransactionId;
461456
ItemId rootlp;
462457
HeapTupleHeader htup;
463458
OffsetNumber latestdead = InvalidOffsetNumber,
464-
maxoff = PageGetMaxOffsetNumber(dp),
465459
offnum;
466460
OffsetNumber chainitems[MaxHeapTuplesPerPage];
467461
int nchain = 0,
468462
i;
469463

470-
rootlp = PageGetItemId(dp, rootoffnum);
464+
rootlp = PageGetItemId(page, rootoffnum);
471465

472466
/*
473467
* If it's a heap-only tuple, then it is not the start of a HOT chain.
474468
*/
475469
if (ItemIdIsNormal(rootlp))
476470
{
477471
Assert(htsv[rootoffnum] != -1);
478-
htup = (HeapTupleHeader) PageGetItem(dp, rootlp);
472+
htup = (HeapTupleHeader) PageGetItem(page, rootlp);
479473

480474
if (HeapTupleHeaderIsHeapOnly(htup))
481475
{
@@ -536,7 +530,7 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum,
536530
if (prstate->marked[offnum])
537531
break;
538532

539-
lp = PageGetItemId(dp, offnum);
533+
lp = PageGetItemId(page, offnum);
540534

541535
/* Unused item obviously isn't part of the chain */
542536
if (!ItemIdIsUsed(lp))
@@ -575,7 +569,7 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum,
575569
}
576570

577571
Assert(ItemIdIsNormal(lp));
578-
htup = (HeapTupleHeader) PageGetItem(dp, lp);
572+
htup = (HeapTupleHeader) PageGetItem(page, lp);
579573

580574
/*
581575
* Check the tuple XMIN against prior XMAX, if any
@@ -666,8 +660,7 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum,
666660
/*
667661
* Advance to next chain member.
668662
*/
669-
Assert(ItemPointerGetBlockNumber(&htup->t_ctid) ==
670-
BufferGetBlockNumber(buffer));
663+
Assert(ItemPointerGetBlockNumber(&htup->t_ctid) == blockno);
671664
offnum = ItemPointerGetOffsetNumber(&htup->t_ctid);
672665
priorXmax = HeapTupleHeaderGetUpdateXid(htup);
673666
}

0 commit comments

Comments
 (0)