mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
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
This commit is contained in:
@ -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;
|
||||||
|
@ -210,6 +210,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 */
|
||||||
@ -218,6 +219,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);
|
||||||
@ -240,12 +242,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
|
||||||
@ -371,8 +369,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)
|
||||||
@ -428,7 +438,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)
|
||||||
@ -669,8 +680,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;
|
||||||
@ -687,6 +698,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));
|
||||||
|
|
||||||
@ -780,7 +792,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;
|
||||||
@ -804,7 +816,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)
|
|||||||
/* 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)
|
|||||||
* 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
|
|||||||
* 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);
|
||||||
|
Reference in New Issue
Block a user