Refactor bitmap heap scan in preparation for parallel support.
authorRobert Haas <rhaas@postgresql.org>
Thu, 2 Mar 2017 13:17:40 +0000 (18:47 +0530)
committerRobert Haas <rhaas@postgresql.org>
Thu, 2 Mar 2017 13:17:40 +0000 (18:47 +0530)
The final patch will be less messy if the prefetching support is
a bit better isolated, so do that.

Dilip Kumar, with some changes by me.  The larger patch set of which
this is a part has been reviewed and tested by (at least) Andres
Freund, Amit Khandekar, Tushar Ahuja, Rafia Sabih, Haribabu Kommi, and
Thomas Munro.

src/backend/executor/nodeBitmapHeapscan.c

index c871aa0348287e1d4466e13f9024269ab9bfa209..c1aa9f13bdf5b3df609ddef3138f34c532762e87 100644 (file)
 
 static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
 static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres);
+static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+                            TBMIterateResult *tbmres);
+static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
+static inline void BitmapPrefetch(BitmapHeapScanState *node,
+              HeapScanDesc scan);
 
 
 /* ----------------------------------------------------------------
@@ -69,10 +74,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
    TIDBitmap  *tbm;
    TBMIterator *tbmiterator;
    TBMIterateResult *tbmres;
-
-#ifdef USE_PREFETCH
-   TBMIterator *prefetch_iterator;
-#endif
    OffsetNumber targoffset;
    TupleTableSlot *slot;
 
@@ -85,9 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
    tbm = node->tbm;
    tbmiterator = node->tbmiterator;
    tbmres = node->tbmres;
-#ifdef USE_PREFETCH
-   prefetch_iterator = node->prefetch_iterator;
-#endif
 
    /*
     * If we haven't yet performed the underlying index scan, do it, and begin
@@ -115,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
 #ifdef USE_PREFETCH
        if (node->prefetch_maximum > 0)
        {
-           node->prefetch_iterator = prefetch_iterator = tbm_begin_iterate(tbm);
+           node->prefetch_iterator = tbm_begin_iterate(tbm);
            node->prefetch_pages = 0;
            node->prefetch_target = -1;
        }
@@ -139,21 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
                break;
            }
 
-#ifdef USE_PREFETCH
-           if (node->prefetch_pages > 0)
-           {
-               /* The main iterator has closed the distance by one page */
-               node->prefetch_pages--;
-           }
-           else if (prefetch_iterator)
-           {
-               /* Do not let the prefetch iterator get behind the main one */
-               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-               if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
-                   elog(ERROR, "prefetch and main iterators are out of sync");
-           }
-#endif   /* USE_PREFETCH */
+           BitmapAdjustPrefetchIterator(node, tbmres);
 
            /*
             * Ignore any claimed entries past what we think is the end of the
@@ -182,23 +166,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
             */
            scan->rs_cindex = 0;
 
-#ifdef USE_PREFETCH
-
-           /*
-            * Increase prefetch target if it's not yet at the max.  Note that
-            * we will increase it to zero after fetching the very first
-            * page/tuple, then to one after the second tuple is fetched, then
-            * it doubles as later pages are fetched.
-            */
-           if (node->prefetch_target >= node->prefetch_maximum)
-                /* don't increase any further */ ;
-           else if (node->prefetch_target >= node->prefetch_maximum / 2)
-               node->prefetch_target = node->prefetch_maximum;
-           else if (node->prefetch_target > 0)
-               node->prefetch_target *= 2;
-           else
-               node->prefetch_target++;
-#endif   /* USE_PREFETCH */
+           /* Adjust the prefetch target */
+           BitmapAdjustPrefetchTarget(node);
        }
        else
        {
@@ -227,8 +196,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
            continue;
        }
 
-#ifdef USE_PREFETCH
-
        /*
         * We issue prefetch requests *after* fetching the current page to try
         * to avoid having prefetching interfere with the main I/O. Also, this
@@ -236,24 +203,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
         * to do on the current page, else we may uselessly prefetch the same
         * page we are just about to request for real.
         */
-       if (prefetch_iterator)
-       {
-           while (node->prefetch_pages < node->prefetch_target)
-           {
-               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
-
-               if (tbmpre == NULL)
-               {
-                   /* No more pages to prefetch */
-                   tbm_end_iterate(prefetch_iterator);
-                   node->prefetch_iterator = prefetch_iterator = NULL;
-                   break;
-               }
-               node->prefetch_pages++;
-               PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
-           }
-       }
-#endif   /* USE_PREFETCH */
+       BitmapPrefetch(node, scan);
 
        /*
         * Okay to fetch the tuple
@@ -411,6 +361,84 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
    scan->rs_ntuples = ntup;
 }
 
+/*
+ * BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
+ */
+static inline void
+BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
+                            TBMIterateResult *tbmres)
+{
+#ifdef USE_PREFETCH
+   TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+   if (node->prefetch_pages > 0)
+   {
+       /* The main iterator has closed the distance by one page */
+       node->prefetch_pages--;
+   }
+   else if (prefetch_iterator)
+   {
+       /* Do not let the prefetch iterator get behind the main one */
+       TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+       if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
+           elog(ERROR, "prefetch and main iterators are out of sync");
+   }
+#endif   /* USE_PREFETCH */
+}
+
+/*
+ * BitmapAdjustPrefetchTarget - Adjust the prefetch target
+ *
+ * Increase prefetch target if it's not yet at the max.  Note that
+ * we will increase it to zero after fetching the very first
+ * page/tuple, then to one after the second tuple is fetched, then
+ * it doubles as later pages are fetched.
+ */
+static inline void
+BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
+{
+#ifdef USE_PREFETCH
+   if (node->prefetch_target >= node->prefetch_maximum)
+        /* don't increase any further */ ;
+   else if (node->prefetch_target >= node->prefetch_maximum / 2)
+       node->prefetch_target = node->prefetch_maximum;
+   else if (node->prefetch_target > 0)
+       node->prefetch_target *= 2;
+   else
+       node->prefetch_target++;
+#endif   /* USE_PREFETCH */
+}
+
+/*
+ * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
+ */
+static inline void
+BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan)
+{
+#ifdef USE_PREFETCH
+   TBMIterator *prefetch_iterator = node->prefetch_iterator;
+
+   if (prefetch_iterator)
+   {
+       while (node->prefetch_pages < node->prefetch_target)
+       {
+           TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+
+           if (tbmpre == NULL)
+           {
+               /* No more pages to prefetch */
+               tbm_end_iterate(prefetch_iterator);
+               node->prefetch_iterator = NULL;
+               break;
+           }
+           node->prefetch_pages++;
+           PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
+       }
+   }
+#endif   /* USE_PREFETCH */
+}
+
 /*
  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
  */