diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-03-07 19:06:50 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-03-07 19:06:50 +0000 |
commit | 8db05ba411ecd3ce2cb0cb7c78fec87658e1a4ab (patch) | |
tree | 7e0fd7aaff03dcd83ef3e4ac0232ae57c268f628 /src/backend/utils/sort/logtape.c | |
parent | e6107da53c93dc188e257d72c3412510d2584093 (diff) | |
download | postgresql-8db05ba411ecd3ce2cb0cb7c78fec87658e1a4ab.tar.gz postgresql-8db05ba411ecd3ce2cb0cb7c78fec87658e1a4ab.zip |
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.
Diffstat (limited to 'src/backend/utils/sort/logtape.c')
-rw-r--r-- | src/backend/utils/sort/logtape.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c index 4f280509cad..6dc203063c9 100644 --- a/src/backend/utils/sort/logtape.c +++ b/src/backend/utils/sort/logtape.c @@ -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[] */ @@ -248,6 +253,12 @@ ltsReleaseBlock(LogicalTapeSet *lts, long blocknum) long *ptr; /* + * Do nothing if we're no longer interested in remembering free space. + */ + if (lts->forgetFreeSpace) + return; + + /* * Enlarge freeBlocks array if full. */ if (lts->nFreeBlocks >= lts->freeBlocksLen) @@ -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; @@ -547,6 +559,21 @@ LogicalTapeSetClose(LogicalTapeSet *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. */ static void |