logtape-prealloc.patch
text/x-patch
Filename: logtape-prealloc.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/sort/logtape.c | 18 | 1 |
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index bc8d56807e2..f44594191e1 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -110,6 +110,7 @@ typedef struct TapeBlockTrailer
#define TapeBlockSetNBytes(buf, nbytes) \
(TapeBlockGetTrailer(buf)->next = -(nbytes))
+#define TAPE_WRITE_N_PREALLOC 32
/*
* This data structure represents a single "logical tape" within the set
@@ -151,6 +152,15 @@ typedef struct LogicalTape
int max_size; /* highest useful, safe buffer_size */
int pos; /* next read/write position in buffer */
int nbytes; /* total # of valid bytes in buffer */
+
+ /*
+ * When multiple tapes are being written to concurrently (as in HashAgg),
+ * it's imporant to preallocate some block numbers to make writes more
+ * sequential. This doesn't preallocate the blocks themselves; only the
+ * block numbers.
+ */
+ int nprealloc;
+ long prealloc[TAPE_WRITE_N_PREALLOC];
} LogicalTape;
/*
@@ -557,6 +567,7 @@ ltsInitTape(LogicalTape *lt)
lt->max_size = MaxAllocSize;
lt->pos = 0;
lt->nbytes = 0;
+ lt->nprealloc = 0;
}
/*
@@ -733,7 +744,13 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
* First allocate the next block, so that we can store it in the
* 'next' pointer of this block.
*/
- nextBlockNumber = ltsGetFreeBlock(lts);
+ if (lt->nprealloc == 0)
+ {
+ lt->nprealloc = TAPE_WRITE_N_PREALLOC;
+ for (int i = lt->nprealloc; i > 0; i--)
+ lt->prealloc[i - 1] = ltsGetFreeBlock(lts);
+ }
+ nextBlockNumber = lt->prealloc[--lt->nprealloc];
/* set the next-pointer and dump the current block. */
TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;