Avoid looping through line pointers twice in PageRepairFragmentation().
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 3 Nov 2017 21:21:59 +0000 (17:21 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 3 Nov 2017 21:21:59 +0000 (17:21 -0400)
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

src/backend/storage/page/bufpage.c

index 41642eb59c41282b7a7d9d0e8aadb0abf9437e1f..b6aa2af818a1cbbb3e75a795b4936ae45b8a1fdd 100644 (file)
@@ -481,6 +481,8 @@ PageRepairFragmentation(Page page)
        Offset          pd_lower = ((PageHeader) page)->pd_lower;
        Offset          pd_upper = ((PageHeader) page)->pd_upper;
        Offset          pd_special = ((PageHeader) page)->pd_special;
+       itemIdSortData itemidbase[MaxHeapTuplesPerPage];
+       itemIdSort      itemidptr;
        ItemId          lp;
        int                     nline,
                                nstorage,
@@ -505,15 +507,31 @@ PageRepairFragmentation(Page page)
                                 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
                                                pd_lower, pd_upper, pd_special)));
 
+       /*
+        * Run through the line pointer array and collect data about live items.
+        */
        nline = PageGetMaxOffsetNumber(page);
-       nunused = nstorage = 0;
+       itemidptr = itemidbase;
+       nunused = totallen = 0;
        for (i = FirstOffsetNumber; i <= nline; i++)
        {
                lp = PageGetItemId(page, i);
                if (ItemIdIsUsed(lp))
                {
                        if (ItemIdHasStorage(lp))
-                               nstorage++;
+                       {
+                               itemidptr->offsetindex = i - 1;
+                               itemidptr->itemoff = ItemIdGetOffset(lp);
+                               if (unlikely(itemidptr->itemoff < (int) pd_upper ||
+                                                        itemidptr->itemoff >= (int) pd_special))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_DATA_CORRUPTED),
+                                                        errmsg("corrupted item pointer: %u",
+                                                                       itemidptr->itemoff)));
+                               itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
+                               totallen += itemidptr->alignedlen;
+                               itemidptr++;
+                       }
                }
                else
                {
@@ -523,6 +541,7 @@ PageRepairFragmentation(Page page)
                }
        }
 
+       nstorage = itemidptr - itemidbase;
        if (nstorage == 0)
        {
                /* Page is completely empty, so just reset it quickly */
@@ -531,29 +550,6 @@ PageRepairFragmentation(Page page)
        else
        {
                /* Need to compact the page the hard way */
-               itemIdSortData itemidbase[MaxHeapTuplesPerPage];
-               itemIdSort      itemidptr = itemidbase;
-
-               totallen = 0;
-               for (i = 0; i < nline; i++)
-               {
-                       lp = PageGetItemId(page, i + 1);
-                       if (ItemIdHasStorage(lp))
-                       {
-                               itemidptr->offsetindex = i;
-                               itemidptr->itemoff = ItemIdGetOffset(lp);
-                               if (itemidptr->itemoff < (int) pd_upper ||
-                                       itemidptr->itemoff >= (int) pd_special)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_DATA_CORRUPTED),
-                                                        errmsg("corrupted item pointer: %u",
-                                                                       itemidptr->itemoff)));
-                               itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
-                               totallen += itemidptr->alignedlen;
-                               itemidptr++;
-                       }
-               }
-
                if (totallen > (Size) (pd_special - pd_lower))
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATA_CORRUPTED),