Commit 07589649 authored by Jeff Davis's avatar Jeff Davis

logtape.c: do not preallocate for tapes when sorting

The preallocation logic is only useful for HashAgg, so disable it when
sorting.

Also, adjust an out-of-date comment.

Reviewed-by: Peter Geoghegan
Discussion: https://postgr.es/m/CAH2-Wzn_o7tE2+hRVvwSFghRb75AJ5g-nqGzDUqLYMexjOAe=g@mail.gmail.com
Backpatch-through: 13
parent 7634bd4f
...@@ -2882,7 +2882,7 @@ hashagg_tapeinfo_init(AggState *aggstate) ...@@ -2882,7 +2882,7 @@ hashagg_tapeinfo_init(AggState *aggstate)
HashTapeInfo *tapeinfo = palloc(sizeof(HashTapeInfo)); HashTapeInfo *tapeinfo = palloc(sizeof(HashTapeInfo));
int init_tapes = 16; /* expanded dynamically */ int init_tapes = 16; /* expanded dynamically */
tapeinfo->tapeset = LogicalTapeSetCreate(init_tapes, NULL, NULL, -1); tapeinfo->tapeset = LogicalTapeSetCreate(init_tapes, true, NULL, NULL, -1);
tapeinfo->ntapes = init_tapes; tapeinfo->ntapes = init_tapes;
tapeinfo->nfreetapes = init_tapes; tapeinfo->nfreetapes = init_tapes;
tapeinfo->freetapes_alloc = init_tapes; tapeinfo->freetapes_alloc = init_tapes;
......
...@@ -212,6 +212,7 @@ struct LogicalTapeSet ...@@ -212,6 +212,7 @@ struct LogicalTapeSet
long *freeBlocks; /* resizable array holding minheap */ long *freeBlocks; /* resizable array holding minheap */
long nFreeBlocks; /* # of currently free blocks */ long nFreeBlocks; /* # of currently free blocks */
Size freeBlocksLen; /* current allocated length of freeBlocks[] */ Size freeBlocksLen; /* current allocated length of freeBlocks[] */
bool enable_prealloc; /* preallocate write blocks? */
/* The array of logical tapes. */ /* The array of logical tapes. */
int nTapes; /* # of logical tapes in set */ int nTapes; /* # of logical tapes in set */
...@@ -220,6 +221,7 @@ struct LogicalTapeSet ...@@ -220,6 +221,7 @@ struct LogicalTapeSet
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer); static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer); static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
static long ltsGetBlock(LogicalTapeSet *lts, LogicalTape *lt);
static long ltsGetFreeBlock(LogicalTapeSet *lts); static long ltsGetFreeBlock(LogicalTapeSet *lts);
static long ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt); static long ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt);
static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum); static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum);
...@@ -242,12 +244,8 @@ ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer) ...@@ -242,12 +244,8 @@ ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
* that's past the current end of file, fill the space between the current * that's past the current end of file, fill the space between the current
* end of file and the target block with zeros. * end of file and the target block with zeros.
* *
* This should happen rarely, otherwise you are not writing very * This can happen either when tapes preallocate blocks; or for the last
* sequentially. In current use, this only happens when the sort ends * block of a tape which might not have been flushed.
* writing a run, and switches to another tape. The last block of the
* previous tape isn't flushed to disk until the end of the sort, so you
* get one-block hole, where the last block of the previous tape will
* later go.
* *
* Note that BufFile concatenation can leave "holes" in BufFile between * Note that BufFile concatenation can leave "holes" in BufFile between
* worker-owned block ranges. These are tracked for reporting purposes * worker-owned block ranges. These are tracked for reporting purposes
...@@ -373,8 +371,20 @@ parent_offset(unsigned long i) ...@@ -373,8 +371,20 @@ parent_offset(unsigned long i)
} }
/* /*
* Select the lowest currently unused block by taking the first element from * Get the next block for writing.
* the freelist min heap. */
static long
ltsGetBlock(LogicalTapeSet *lts, LogicalTape *lt)
{
if (lts->enable_prealloc)
return ltsGetPreallocBlock(lts, lt);
else
return ltsGetFreeBlock(lts);
}
/*
* Select the lowest currently unused block from the tape set's global free
* list min heap.
*/ */
static long static long
ltsGetFreeBlock(LogicalTapeSet *lts) ltsGetFreeBlock(LogicalTapeSet *lts)
...@@ -430,7 +440,8 @@ ltsGetFreeBlock(LogicalTapeSet *lts) ...@@ -430,7 +440,8 @@ ltsGetFreeBlock(LogicalTapeSet *lts)
/* /*
* Return the lowest free block number from the tape's preallocation list. * Return the lowest free block number from the tape's preallocation list.
* Refill the preallocation list if necessary. * Refill the preallocation list with blocks from the tape set's free list if
* necessary.
*/ */
static long static long
ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt) ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt)
...@@ -671,8 +682,8 @@ ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt) ...@@ -671,8 +682,8 @@ ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
* infrastructure that may be lifted in the future. * infrastructure that may be lifted in the future.
*/ */
LogicalTapeSet * LogicalTapeSet *
LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset, LogicalTapeSetCreate(int ntapes, bool preallocate, TapeShare *shared,
int worker) SharedFileSet *fileset, int worker)
{ {
LogicalTapeSet *lts; LogicalTapeSet *lts;
int i; int i;
...@@ -689,6 +700,7 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset, ...@@ -689,6 +700,7 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset,
lts->freeBlocksLen = 32; /* reasonable initial guess */ lts->freeBlocksLen = 32; /* reasonable initial guess */
lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long)); lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
lts->nFreeBlocks = 0; lts->nFreeBlocks = 0;
lts->enable_prealloc = preallocate;
lts->nTapes = ntapes; lts->nTapes = ntapes;
lts->tapes = (LogicalTape *) palloc(ntapes * sizeof(LogicalTape)); lts->tapes = (LogicalTape *) palloc(ntapes * sizeof(LogicalTape));
...@@ -782,7 +794,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum, ...@@ -782,7 +794,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
Assert(lt->firstBlockNumber == -1); Assert(lt->firstBlockNumber == -1);
Assert(lt->pos == 0); Assert(lt->pos == 0);
lt->curBlockNumber = ltsGetPreallocBlock(lts, lt); lt->curBlockNumber = ltsGetBlock(lts, lt);
lt->firstBlockNumber = lt->curBlockNumber; lt->firstBlockNumber = lt->curBlockNumber;
TapeBlockGetTrailer(lt->buffer)->prev = -1L; TapeBlockGetTrailer(lt->buffer)->prev = -1L;
...@@ -806,7 +818,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum, ...@@ -806,7 +818,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
* First allocate the next block, so that we can store it in the * First allocate the next block, so that we can store it in the
* 'next' pointer of this block. * 'next' pointer of this block.
*/ */
nextBlockNumber = ltsGetPreallocBlock(lts, lt); nextBlockNumber = ltsGetBlock(lts, lt);
/* set the next-pointer and dump the current block. */ /* set the next-pointer and dump the current block. */
TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber; TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;
......
...@@ -2591,7 +2591,7 @@ inittapes(Tuplesortstate *state, bool mergeruns) ...@@ -2591,7 +2591,7 @@ inittapes(Tuplesortstate *state, bool mergeruns)
/* Create the tape set and allocate the per-tape data arrays */ /* Create the tape set and allocate the per-tape data arrays */
inittapestate(state, maxTapes); inittapestate(state, maxTapes);
state->tapeset = state->tapeset =
LogicalTapeSetCreate(maxTapes, NULL, LogicalTapeSetCreate(maxTapes, false, NULL,
state->shared ? &state->shared->fileset : NULL, state->shared ? &state->shared->fileset : NULL,
state->worker); state->worker);
...@@ -4657,8 +4657,9 @@ leader_takeover_tapes(Tuplesortstate *state) ...@@ -4657,8 +4657,9 @@ leader_takeover_tapes(Tuplesortstate *state)
* randomAccess is disallowed for parallel sorts. * randomAccess is disallowed for parallel sorts.
*/ */
inittapestate(state, nParticipants + 1); inittapestate(state, nParticipants + 1);
state->tapeset = LogicalTapeSetCreate(nParticipants + 1, shared->tapes, state->tapeset = LogicalTapeSetCreate(nParticipants + 1, false,
&shared->fileset, state->worker); shared->tapes, &shared->fileset,
state->worker);
/* mergeruns() relies on currentRun for # of runs (in one-pass cases) */ /* mergeruns() relies on currentRun for # of runs (in one-pass cases) */
state->currentRun = nParticipants; state->currentRun = nParticipants;
......
...@@ -54,7 +54,8 @@ typedef struct TapeShare ...@@ -54,7 +54,8 @@ typedef struct TapeShare
* prototypes for functions in logtape.c * prototypes for functions in logtape.c
*/ */
extern LogicalTapeSet *LogicalTapeSetCreate(int ntapes, TapeShare *shared, extern LogicalTapeSet *LogicalTapeSetCreate(int ntapes, bool preallocate,
TapeShare *shared,
SharedFileSet *fileset, int worker); SharedFileSet *fileset, int worker);
extern void LogicalTapeSetClose(LogicalTapeSet *lts); extern void LogicalTapeSetClose(LogicalTapeSet *lts);
extern void LogicalTapeSetForgetFreeSpace(LogicalTapeSet *lts); extern void LogicalTapeSetForgetFreeSpace(LogicalTapeSet *lts);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment