]> granicus.if.org Git - postgresql/commitdiff
Fix excessive memory consumption in the new sort pre-reading code.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 6 Oct 2016 06:46:40 +0000 (09:46 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 6 Oct 2016 06:46:40 +0000 (09:46 +0300)
LogicalTapeRewind() should not allocate large read buffer, if the tape
is completely empty. The calling code relies on that, for its
calculation of how much memory to allocate for the read buffers. That
lead to massive overallocation of memory, if maxTapes was high, but
only a few tapes were actually used.

Reported by Tomas Vondra

Discussion: <7303da46-daf7-9c68-3cc1-9f83235cf37e@2ndquadrant.com>

src/backend/utils/sort/logtape.c

index caa6960b95795eaad14a2fba659d203b2d0b510f..6cc06b24e0db0ed39180a21afcaa420601f54c2d 100644 (file)
@@ -778,11 +778,16 @@ LogicalTapeRewind(LogicalTapeSet *lts, int tapenum, bool forWrite)
                        datablocknum = ltsRewindFrozenIndirectBlock(lts, lt->indirect);
                }
 
-               /* Allocate a read buffer */
+               /* Allocate a read buffer (unless the tape is empty) */
                if (lt->buffer)
                        pfree(lt->buffer);
-               lt->buffer = palloc(lt->read_buffer_size);
-               lt->buffer_size = lt->read_buffer_size;
+               lt->buffer = NULL;
+               lt->buffer_size = 0;
+               if (datablocknum != -1L)
+               {
+                       lt->buffer = palloc(lt->read_buffer_size);
+                       lt->buffer_size = lt->read_buffer_size;
+               }
 
                /* Read the first block, or reset if tape is empty */
                lt->curBlockNumber = 0L;