Skip to content

Commit a9169f0

Browse files
committed
Avoid looping through line pointers twice in PageRepairFragmentation().
There doesn't seem to be any good reason to do the filling of the itemidbase[] array separately from the first traversal of the pointers. It's certainly not a win if there are any line pointers with storage, and even if there aren't, this change doesn't insert code into the part of the first loop that will be traversed in that case. So let's just merge the two loops. Yura Sokolov, reviewed by Claudio Freire Discussion: https://postgr.es/m/e49befcc6f1d7099834c6fdf5c675a60@postgrespro.ru
1 parent 4c11d2c commit a9169f0

File tree

1 file changed

+21
-25
lines changed

1 file changed

+21
-25
lines changed

src/backend/storage/page/bufpage.c

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ PageRepairFragmentation(Page page)
481481
Offset pd_lower = ((PageHeader) page)->pd_lower;
482482
Offset pd_upper = ((PageHeader) page)->pd_upper;
483483
Offset pd_special = ((PageHeader) page)->pd_special;
484+
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
485+
itemIdSort itemidptr;
484486
ItemId lp;
485487
int nline,
486488
nstorage,
@@ -505,15 +507,31 @@ PageRepairFragmentation(Page page)
505507
errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
506508
pd_lower, pd_upper, pd_special)));
507509

510+
/*
511+
* Run through the line pointer array and collect data about live items.
512+
*/
508513
nline = PageGetMaxOffsetNumber(page);
509-
nunused = nstorage = 0;
514+
itemidptr = itemidbase;
515+
nunused = totallen = 0;
510516
for (i = FirstOffsetNumber; i <= nline; i++)
511517
{
512518
lp = PageGetItemId(page, i);
513519
if (ItemIdIsUsed(lp))
514520
{
515521
if (ItemIdHasStorage(lp))
516-
nstorage++;
522+
{
523+
itemidptr->offsetindex = i - 1;
524+
itemidptr->itemoff = ItemIdGetOffset(lp);
525+
if (unlikely(itemidptr->itemoff < (int) pd_upper ||
526+
itemidptr->itemoff >= (int) pd_special))
527+
ereport(ERROR,
528+
(errcode(ERRCODE_DATA_CORRUPTED),
529+
errmsg("corrupted item pointer: %u",
530+
itemidptr->itemoff)));
531+
itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
532+
totallen += itemidptr->alignedlen;
533+
itemidptr++;
534+
}
517535
}
518536
else
519537
{
@@ -523,6 +541,7 @@ PageRepairFragmentation(Page page)
523541
}
524542
}
525543

544+
nstorage = itemidptr - itemidbase;
526545
if (nstorage == 0)
527546
{
528547
/* Page is completely empty, so just reset it quickly */
@@ -531,29 +550,6 @@ PageRepairFragmentation(Page page)
531550
else
532551
{
533552
/* Need to compact the page the hard way */
534-
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
535-
itemIdSort itemidptr = itemidbase;
536-
537-
totallen = 0;
538-
for (i = 0; i < nline; i++)
539-
{
540-
lp = PageGetItemId(page, i + 1);
541-
if (ItemIdHasStorage(lp))
542-
{
543-
itemidptr->offsetindex = i;
544-
itemidptr->itemoff = ItemIdGetOffset(lp);
545-
if (itemidptr->itemoff < (int) pd_upper ||
546-
itemidptr->itemoff >= (int) pd_special)
547-
ereport(ERROR,
548-
(errcode(ERRCODE_DATA_CORRUPTED),
549-
errmsg("corrupted item pointer: %u",
550-
itemidptr->itemoff)));
551-
itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
552-
totallen += itemidptr->alignedlen;
553-
itemidptr++;
554-
}
555-
}
556-
557553
if (totallen > (Size) (pd_special - pd_lower))
558554
ereport(ERROR,
559555
(errcode(ERRCODE_DATA_CORRUPTED),

0 commit comments

Comments
 (0)