mirror of
https://github.com/postgres/postgres.git
synced 2025-12-02 23:42:46 +03:00
Repair old performance bug in tuplesort.c/logtape.c. In the case where
we are doing the final merge pass on-the-fly, and not writing the data back onto a 'tape', the number of free blocks in the tape set will become large, leading to a lot of time wasted in ltsReleaseBlock(). There is really no need to track the free blocks anymore in this state, so add a simple shutoff switch. Per report from Stefan Kaltenbrunner.
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.19 2006/03/05 15:58:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.20 2006/03/07 19:06:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -146,7 +146,12 @@ struct LogicalTapeSet
|
||||
* When there are no such blocks, we extend the underlying file. Note
|
||||
* that the block numbers in freeBlocks are always in *decreasing* order,
|
||||
* so that removing the last entry gives us the lowest free block.
|
||||
*
|
||||
* If forgetFreeSpace is true then any freed blocks are simply forgotten
|
||||
* rather than being remembered in freeBlocks[]. See notes for
|
||||
* LogicalTapeSetForgetFreeSpace().
|
||||
*/
|
||||
bool forgetFreeSpace; /* are we remembering free blocks? */
|
||||
long *freeBlocks; /* resizable array */
|
||||
int nFreeBlocks; /* # of currently free blocks */
|
||||
int freeBlocksLen; /* current allocated length of freeBlocks[] */
|
||||
@@ -247,6 +252,12 @@ ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
|
||||
int ndx;
|
||||
long *ptr;
|
||||
|
||||
/*
|
||||
* Do nothing if we're no longer interested in remembering free space.
|
||||
*/
|
||||
if (lts->forgetFreeSpace)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Enlarge freeBlocks array if full.
|
||||
*/
|
||||
@@ -491,6 +502,7 @@ LogicalTapeSetCreate(int ntapes)
|
||||
(ntapes - 1) * sizeof(LogicalTape));
|
||||
lts->pfile = BufFileCreateTemp(false);
|
||||
lts->nFileBlocks = 0L;
|
||||
lts->forgetFreeSpace = false;
|
||||
lts->freeBlocksLen = 32; /* reasonable initial guess */
|
||||
lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
|
||||
lts->nFreeBlocks = 0;
|
||||
@@ -546,6 +558,21 @@ LogicalTapeSetClose(LogicalTapeSet *lts)
|
||||
pfree(lts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a logical tape set as not needing management of free space anymore.
|
||||
*
|
||||
* This should be called if the caller does not intend to write any more data
|
||||
* into the tape set, but is reading from un-frozen tapes. Since no more
|
||||
* writes are planned, remembering free blocks is no longer useful. Setting
|
||||
* this flag lets us avoid wasting time and space in ltsReleaseBlock(), which
|
||||
* is not designed to handle large numbers of free blocks.
|
||||
*/
|
||||
void
|
||||
LogicalTapeSetForgetFreeSpace(LogicalTapeSet *lts)
|
||||
{
|
||||
lts->forgetFreeSpace = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the dirty buffer of a logical tape.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user