Read from the same worker repeatedly until it returns no tuple.
authorRobert Haas
Wed, 23 Dec 2015 19:06:52 +0000 (14:06 -0500)
committerRobert Haas
Wed, 23 Dec 2015 19:06:52 +0000 (14:06 -0500)
The original coding read tuples from workers in round-robin fashion,
but performance testing shows that it works much better to read enough
to empty one queue before moving on to the next.  I believe the
reason for this is that, with the old approach, we could easily wake
up a worker repeatedly to write only one new tuple into the shm_mq
each time.  With this approach, by the time the process gets scheduled,
it has a decent chance of being able to fill the entire buffer in
one go.

Patch by me.  Dilip Kumar helped with performance testing.

src/backend/executor/nodeGather.c

index f32da1e2352e7061d1535f4da968386de7785906..db5883d28ef2e59f5944f7af6eccef9943ef3244 100644 (file)
@@ -359,14 +359,20 @@ gather_readnext(GatherState *gatherstate)
            continue;
        }
 
-       /* Advance nextreader pointer in round-robin fashion. */
-       gatherstate->nextreader =
-           (gatherstate->nextreader + 1) % gatherstate->nreaders;
-
        /* If we got a tuple, return it. */
        if (tup)
            return tup;
 
+       /*
+        * Advance nextreader pointer in round-robin fashion.  Note that we
+        * only reach this code if we weren't able to get a tuple from the
+        * current worker.  We used to advance the nextreader pointer after
+        * every tuple, but it turns out to be much more efficient to keep
+        * reading from the same queue until that would require blocking.
+        */
+       gatherstate->nextreader =
+           (gatherstate->nextreader + 1) % gatherstate->nreaders;
+
        /* Have we visited every TupleQueueReader? */
        if (gatherstate->nextreader == waitpos)
        {