Make tbm_add_tuples more efficient by caching the last acccessed page.
authorAndres Freund <[email protected]>
Fri, 16 Jan 2015 16:47:59 +0000 (17:47 +0100)
committerAndres Freund <[email protected]>
Fri, 16 Jan 2015 16:47:59 +0000 (17:47 +0100)
When adding a large number of tuples to a TID bitmap using
tbm_add_tuples() sometimes a lot of time was spent looking up a page's
entry in the bitmap's internal hashtable.

Improve efficiency by caching the last accessed page, while iterating
over the passed in tuples, hoping consecutive tuples will often be on
the same page.  In many cases that's a good bet, and in the rest the
added overhead isn't big.

Discussion: 54479A85.8060309@sigaev.ru

Author: Teodor Sigaev
Reviewed-By: David Rowley
src/backend/nodes/tidbitmap.c

index d8248b1832fa0f987a6da1326c97689dab0e376b..dd1c6657fa7e1edb142ff06e6434d55bb1928a67 100644 (file)
@@ -268,14 +268,14 @@ void
 tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
               bool recheck)
 {
-   int         i;
+   int             i;
+   PagetableEntry *page = NULL;
 
    Assert(!tbm->iterating);
    for (i = 0; i < ntids; i++)
    {
        BlockNumber blk = ItemPointerGetBlockNumber(tids + i);
        OffsetNumber off = ItemPointerGetOffsetNumber(tids + i);
-       PagetableEntry *page;
        int         wordnum,
                    bitnum;
 
@@ -283,10 +283,18 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
        if (off < 1 || off > MAX_TUPLES_PER_PAGE)
            elog(ERROR, "tuple offset out of range: %u", off);
 
-       if (tbm_page_is_lossy(tbm, blk))
-           continue;           /* whole page is already marked */
-
-       page = tbm_get_pageentry(tbm, blk);
+       if (page == NULL || page->blockno != blk)
+       {
+           if (tbm_page_is_lossy(tbm, blk))
+               continue;   /* whole page is already marked */
+
+           /*
+            * Cache this page as it's quite likely that we'll see the same
+            * page again in the next iteration. This will save having to
+            * lookup the page in the hashtable again.
+            */
+           page = tbm_get_pageentry(tbm, blk);
+       }
 
        if (page->ischunk)
        {
@@ -303,7 +311,11 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids,
        page->recheck |= recheck;
 
        if (tbm->nentries > tbm->maxentries)
+       {
            tbm_lossify(tbm);
+           /* Cached page could become lossy or freed */
+           page = NULL;
+       }
    }
 }