diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/init/globals.c | 4 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 4 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 2 | ||||
-rw-r--r-- | src/backend/utils/mmgr/aset.c | 24 | ||||
-rw-r--r-- | src/backend/utils/mmgr/mcxt.c | 35 | ||||
-rw-r--r-- | src/backend/utils/sort/tuplesort.c | 141 | ||||
-rw-r--r-- | src/backend/utils/sort/tuplestore.c | 46 | ||||
-rw-r--r-- | src/include/nodes/memnodes.h | 5 | ||||
-rw-r--r-- | src/include/utils/memutils.h | 5 |
9 files changed, 136 insertions, 130 deletions
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index cec975719e1..51a729c49c6 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.65 2002/06/20 20:29:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.66 2002/08/12 00:36:11 tgl Exp $ * * NOTES * Globals used all over the place should be declared here and not @@ -71,6 +71,6 @@ char FloatFormat[20] = "%f"; bool enableFsync = true; bool allowSystemTableMods = false; -int SortMem = 512; +int SortMem = 1024; int VacuumMem = 8192; int NBuffers = DEF_NBUFFERS; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ebb4a7d89bb..d94010cb598 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.78 2002/08/07 17:26:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.79 2002/08/12 00:36:11 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut <peter_e@gmx.net>. @@ -556,7 +556,7 @@ static struct config_int { { "sort_mem", PGC_USERSET }, &SortMem, - 512, 4 * BLCKSZ / 1024, INT_MAX, NULL, NULL + 1024, 8 * BLCKSZ / 1024, INT_MAX, NULL, NULL }, { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index be097186cac..c9511ad7fb1 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -57,7 +57,7 @@ # # Non-shared Memory Sizes # -#sort_mem = 512 # min 32 +#sort_mem = 1024 # min 64 #vacuum_mem = 8192 # min 1024 diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 5dc20557dd2..9cfcabbc9f8 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.46 2002/06/20 20:29:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.47 2002/08/12 00:36:12 tgl Exp $ * * NOTE: * This is a new (Feb. 05, 1999) implementation of the allocation set @@ -204,11 +204,11 @@ static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size); static void AllocSetInit(MemoryContext context); static void AllocSetReset(MemoryContext context); static void AllocSetDelete(MemoryContext context); - +static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer); +static void AllocSetStats(MemoryContext context); #ifdef MEMORY_CONTEXT_CHECKING static void AllocSetCheck(MemoryContext context); #endif -static void AllocSetStats(MemoryContext context); /* * This is the virtual function table for AllocSet contexts. @@ -220,10 +220,11 @@ static MemoryContextMethods AllocSetMethods = { AllocSetInit, AllocSetReset, AllocSetDelete, + AllocSetGetChunkSpace, + AllocSetStats #ifdef MEMORY_CONTEXT_CHECKING - AllocSetCheck, + , AllocSetCheck #endif - AllocSetStats }; @@ -954,6 +955,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) } /* + * AllocSetGetChunkSpace + * Given a currently-allocated chunk, determine the total space + * it occupies (including all memory-allocation overhead). + */ +static Size +AllocSetGetChunkSpace(MemoryContext context, void *pointer) +{ + AllocChunk chunk = AllocPointerGetChunk(pointer); + + return chunk->size + ALLOC_CHUNKHDRSZ; +} + +/* * AllocSetStats * Displays stats about memory consumption of an allocset. */ diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 709bd74d328..6b77736a3bc 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.31 2002/08/10 20:29:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.32 2002/08/12 00:36:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -225,6 +225,39 @@ MemoryContextResetAndDeleteChildren(MemoryContext context) } /* + * GetMemoryChunkSpace + * Given a currently-allocated chunk, determine the total space + * it occupies (including all memory-allocation overhead). + * + * This is useful for measuring the total space occupied by a set of + * allocated chunks. + */ +Size +GetMemoryChunkSpace(void *pointer) +{ + StandardChunkHeader *header; + + /* + * Try to detect bogus pointers handed to us, poorly though we can. + * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an + * allocated chunk. + */ + Assert(pointer != NULL); + Assert(pointer == (void *) MAXALIGN(pointer)); + + /* + * OK, it's probably safe to look at the chunk header. + */ + header = (StandardChunkHeader *) + ((char *) pointer - STANDARDCHUNKHEADERSIZE); + + AssertArg(MemoryContextIsValid(header->context)); + + return (*header->context->methods->get_chunk_space) (header->context, + pointer); +} + +/* * MemoryContextStats * Print statistics about the named context and all its descendants. * diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 0ceda772fdc..a7a387e6752 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -78,7 +78,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.24 2002/06/20 20:29:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.25 2002/08/12 00:36:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -167,13 +167,6 @@ struct Tuplesortstate void *(*readtup) (Tuplesortstate *state, int tapenum, unsigned int len); /* - * Obtain memory space occupied by a stored tuple. (This routine is - * only needed in the FINALMERGE case, since copytup, writetup, and - * readtup are expected to adjust availMem appropriately.) - */ - unsigned int (*tuplesize) (Tuplesortstate *state, void *tup); - - /* * This array holds pointers to tuples in sort memory. If we are in * state INITIAL, the tuples are in no particular order; if we are in * state SORTEDINMEM, the tuples are in final sorted order; in states @@ -295,7 +288,6 @@ struct Tuplesortstate #define COPYTUP(state,tup) ((*(state)->copytup) (state, tup)) #define WRITETUP(state,tape,tup) ((*(state)->writetup) (state, tape, tup)) #define READTUP(state,tape,len) ((*(state)->readtup) (state, tape, len)) -#define TUPLESIZE(state,tup) ((*(state)->tuplesize) (state, tup)) #define LACKMEM(state) ((state)->availMem < 0) #define USEMEM(state,amt) ((state)->availMem -= (amt)) #define FREEMEM(state,amt) ((state)->availMem += (amt)) @@ -331,30 +323,16 @@ struct Tuplesortstate * * NOTES about memory consumption calculations: * - * We count space requested for tuples against the SortMem limit. + * We count space allocated for tuples against the SortMem limit, plus + * the space used by the variable-size arrays memtuples and memtupindex. * Fixed-size space (primarily the LogicalTapeSet I/O buffers) is not - * counted, nor do we count the variable-size memtuples and memtupindex - * arrays. (Even though those could grow pretty large, they should be - * small compared to the tuples proper, so this is not unreasonable.) - * - * The major deficiency in this approach is that it ignores palloc overhead. - * The memory space actually allocated for a palloc chunk is always more - * than the request size, and could be considerably more (as much as 2X - * larger, in the current aset.c implementation). So the space used could - * be considerably more than SortMem says. + * counted. * - * One way to fix this is to add a memory management function that, given - * a pointer to a palloc'd chunk, returns the actual space consumed by the - * chunk. This would be very easy in the current aset.c module, but I'm - * hesitant to do it because it might be unpleasant to support in future - * implementations of memory management. (For example, a direct - * implementation of palloc as malloc could not support such a function - * portably.) - * - * A cruder answer is just to apply a fudge factor, say by initializing - * availMem to only three-quarters of what SortMem indicates. This is - * probably the right answer if anyone complains that SortMem is not being - * obeyed very faithfully. + * Note that we count actual space used (as shown by GetMemoryChunkSpace) + * rather than the originally-requested size. This is important since + * palloc can add substantial overhead. It's not a complete answer since + * we won't count any wasted space in palloc allocation blocks, but it's + * a lot better than what we were doing before 7.3. * *-------------------- */ @@ -394,21 +372,18 @@ static void *copytup_heap(Tuplesortstate *state, void *tup); static void writetup_heap(Tuplesortstate *state, int tapenum, void *tup); static void *readtup_heap(Tuplesortstate *state, int tapenum, unsigned int len); -static unsigned int tuplesize_heap(Tuplesortstate *state, void *tup); static int comparetup_index(Tuplesortstate *state, const void *a, const void *b); static void *copytup_index(Tuplesortstate *state, void *tup); static void writetup_index(Tuplesortstate *state, int tapenum, void *tup); static void *readtup_index(Tuplesortstate *state, int tapenum, unsigned int len); -static unsigned int tuplesize_index(Tuplesortstate *state, void *tup); static int comparetup_datum(Tuplesortstate *state, const void *a, const void *b); static void *copytup_datum(Tuplesortstate *state, void *tup); static void writetup_datum(Tuplesortstate *state, int tapenum, void *tup); static void *readtup_datum(Tuplesortstate *state, int tapenum, unsigned int len); -static unsigned int tuplesize_datum(Tuplesortstate *state, void *tup); /* * Since qsort(3) will not pass any context info to qsort_comparetup(), @@ -453,6 +428,8 @@ tuplesort_begin_common(bool randomAccess) state->memtupindex = NULL; /* until and unless needed */ + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + state->currentRun = 0; /* Algorithm D variables will be initialized by inittapes, if needed */ @@ -478,7 +455,6 @@ tuplesort_begin_heap(TupleDesc tupDesc, state->copytup = copytup_heap; state->writetup = writetup_heap; state->readtup = readtup_heap; - state->tuplesize = tuplesize_heap; state->tupDesc = tupDesc; state->nKeys = nkeys; @@ -520,7 +496,6 @@ tuplesort_begin_index(Relation indexRel, state->copytup = copytup_index; state->writetup = writetup_index; state->readtup = readtup_index; - state->tuplesize = tuplesize_index; state->indexRel = indexRel; /* see comments below about btree dependence of this code... */ @@ -544,7 +519,6 @@ tuplesort_begin_datum(Oid datumType, state->copytup = copytup_datum; state->writetup = writetup_datum; state->readtup = readtup_datum; - state->tuplesize = tuplesize_datum; state->datumType = datumType; state->sortOperator = sortOperator; @@ -627,7 +601,6 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull) */ if (isNull || state->datumTypeByVal) { - USEMEM(state, sizeof(DatumTuple)); tuple = (DatumTuple *) palloc(sizeof(DatumTuple)); tuple->val = val; tuple->isNull = isNull; @@ -641,7 +614,6 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull) if (datalen == -1) /* variable length type? */ datalen = VARSIZE((struct varlena *) DatumGetPointer(val)); tuplelen = datalen + MAXALIGN(sizeof(DatumTuple)); - USEMEM(state, tuplelen); newVal = (char *) palloc(tuplelen); tuple = (DatumTuple *) newVal; newVal += MAXALIGN(sizeof(DatumTuple)); @@ -650,6 +622,8 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull) tuple->isNull = false; } + USEMEM(state, GetMemoryChunkSpace(tuple)); + puttuple_common(state, (void *) tuple); } @@ -669,10 +643,12 @@ puttuple_common(Tuplesortstate *state, void *tuple) if (state->memtupcount >= state->memtupsize) { /* Grow the unsorted array as needed. */ + FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); state->memtupsize *= 2; state->memtuples = (void **) repalloc(state->memtuples, state->memtupsize * sizeof(void *)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); } state->memtuples[state->memtupcount++] = tuple; @@ -914,13 +890,13 @@ tuplesort_gettuple(Tuplesortstate *state, bool forward, if (state->memtupcount > 0) { int srcTape = state->memtupindex[0]; - unsigned int tuplen; + Size tuplen; int tupIndex; void *newtup; tup = state->memtuples[0]; /* returned tuple is no longer counted in our memory space */ - tuplen = TUPLESIZE(state, tup); + tuplen = GetMemoryChunkSpace(tup); state->availMem += tuplen; state->mergeavailmem[srcTape] += tuplen; tuplesort_heap_siftup(state, false); @@ -1019,6 +995,8 @@ inittapes(Tuplesortstate *state) */ state->memtupindex = (int *) palloc(state->memtupsize * sizeof(int)); + USEMEM(state, GetMemoryChunkSpace(state->memtupindex)); + /* * Convert the unsorted contents of memtuples[] into a heap. Each * tuple is marked as belonging to run number zero. @@ -1408,6 +1386,8 @@ mergepreread(Tuplesortstate *state) /* Might need to enlarge arrays! */ if (tupIndex >= state->memtupsize) { + FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); + FREEMEM(state, GetMemoryChunkSpace(state->memtupindex)); state->memtupsize *= 2; state->memtuples = (void **) repalloc(state->memtuples, @@ -1415,6 +1395,8 @@ mergepreread(Tuplesortstate *state) state->memtupindex = (int *) repalloc(state->memtupindex, state->memtupsize * sizeof(int)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + USEMEM(state, GetMemoryChunkSpace(state->memtupindex)); } } /* store tuple, append to list for its tape */ @@ -1604,6 +1586,8 @@ tuplesort_heap_insert(Tuplesortstate *state, void *tuple, */ if (state->memtupcount >= state->memtupsize) { + FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); + FREEMEM(state, GetMemoryChunkSpace(state->memtupindex)); state->memtupsize *= 2; state->memtuples = (void **) repalloc(state->memtuples, @@ -1611,6 +1595,8 @@ tuplesort_heap_insert(Tuplesortstate *state, void *tuple, state->memtupindex = (int *) repalloc(state->memtupindex, state->memtupsize * sizeof(int)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + USEMEM(state, GetMemoryChunkSpace(state->memtupindex)); } memtuples = state->memtuples; memtupindex = state->memtupindex; @@ -1761,8 +1747,9 @@ copytup_heap(Tuplesortstate *state, void *tup) { HeapTuple tuple = (HeapTuple) tup; - USEMEM(state, HEAPTUPLESIZE + tuple->t_len); - return (void *) heap_copytuple(tuple); + tuple = heap_copytuple(tuple); + USEMEM(state, GetMemoryChunkSpace(tuple)); + return (void *) tuple; } /* @@ -1784,7 +1771,7 @@ writetup_heap(Tuplesortstate *state, int tapenum, void *tup) LogicalTapeWrite(state->tapeset, tapenum, (void *) &tuplen, sizeof(tuplen)); - FREEMEM(state, HEAPTUPLESIZE + tuple->t_len); + FREEMEM(state, GetMemoryChunkSpace(tuple)); heap_freetuple(tuple); } @@ -1794,7 +1781,7 @@ readtup_heap(Tuplesortstate *state, int tapenum, unsigned int len) unsigned int tuplen = len - sizeof(unsigned int) + HEAPTUPLESIZE; HeapTuple tuple = (HeapTuple) palloc(tuplen); - USEMEM(state, tuplen); + USEMEM(state, GetMemoryChunkSpace(tuple)); /* reconstruct the HeapTupleData portion */ tuple->t_len = len - sizeof(unsigned int); ItemPointerSetInvalid(&(tuple->t_self)); @@ -1811,14 +1798,6 @@ readtup_heap(Tuplesortstate *state, int tapenum, unsigned int len) return (void *) tuple; } -static unsigned int -tuplesize_heap(Tuplesortstate *state, void *tup) -{ - HeapTuple tuple = (HeapTuple) tup; - - return HEAPTUPLESIZE + tuple->t_len; -} - /* * Routines specialized for IndexTuple case @@ -1901,8 +1880,9 @@ copytup_index(Tuplesortstate *state, void *tup) unsigned int tuplen = IndexTupleSize(tuple); IndexTuple newtuple; - USEMEM(state, tuplen); newtuple = (IndexTuple) palloc(tuplen); + USEMEM(state, GetMemoryChunkSpace(newtuple)); + memcpy(newtuple, tuple, tuplen); return (void *) newtuple; @@ -1923,7 +1903,7 @@ writetup_index(Tuplesortstate *state, int tapenum, void *tup) LogicalTapeWrite(state->tapeset, tapenum, (void *) &tuplen, sizeof(tuplen)); - FREEMEM(state, IndexTupleSize(tuple)); + FREEMEM(state, GetMemoryChunkSpace(tuple)); pfree(tuple); } @@ -1933,7 +1913,7 @@ readtup_index(Tuplesortstate *state, int tapenum, unsigned int len) unsigned int tuplen = len - sizeof(unsigned int); IndexTuple tuple = (IndexTuple) palloc(tuplen); - USEMEM(state, tuplen); + USEMEM(state, GetMemoryChunkSpace(tuple)); if (LogicalTapeRead(state->tapeset, tapenum, (void *) tuple, tuplen) != tuplen) elog(ERROR, "tuplesort: unexpected end of data"); @@ -1944,15 +1924,6 @@ readtup_index(Tuplesortstate *state, int tapenum, unsigned int len) return (void *) tuple; } -static unsigned int -tuplesize_index(Tuplesortstate *state, void *tup) -{ - IndexTuple tuple = (IndexTuple) tup; - unsigned int tuplen = IndexTupleSize(tuple); - - return tuplen; -} - /* * Routines specialized for DatumTuple case @@ -1981,8 +1952,21 @@ static void writetup_datum(Tuplesortstate *state, int tapenum, void *tup) { DatumTuple *tuple = (DatumTuple *) tup; - unsigned int tuplen = tuplesize_datum(state, tup); - unsigned int writtenlen = tuplen + sizeof(unsigned int); + unsigned int tuplen; + unsigned int writtenlen; + + if (tuple->isNull || state->datumTypeByVal) + tuplen = sizeof(DatumTuple); + else + { + int datalen = state->datumTypeLen; + + if (datalen == -1) /* variable length type? */ + datalen = VARSIZE((struct varlena *) DatumGetPointer(tuple->val)); + tuplen = datalen + MAXALIGN(sizeof(DatumTuple)); + } + + writtenlen = tuplen + sizeof(unsigned int); LogicalTapeWrite(state->tapeset, tapenum, (void *) &writtenlen, sizeof(writtenlen)); @@ -1992,7 +1976,7 @@ writetup_datum(Tuplesortstate *state, int tapenum, void *tup) LogicalTapeWrite(state->tapeset, tapenum, (void *) &writtenlen, sizeof(writtenlen)); - FREEMEM(state, tuplen); + FREEMEM(state, GetMemoryChunkSpace(tuple)); pfree(tuple); } @@ -2002,7 +1986,7 @@ readtup_datum(Tuplesortstate *state, int tapenum, unsigned int len) unsigned int tuplen = len - sizeof(unsigned int); DatumTuple *tuple = (DatumTuple *) palloc(tuplen); - USEMEM(state, tuplen); + USEMEM(state, GetMemoryChunkSpace(tuple)); if (LogicalTapeRead(state->tapeset, tapenum, (void *) tuple, tuplen) != tuplen) elog(ERROR, "tuplesort: unexpected end of data"); @@ -2017,25 +2001,6 @@ readtup_datum(Tuplesortstate *state, int tapenum, unsigned int len) return (void *) tuple; } -static unsigned int -tuplesize_datum(Tuplesortstate *state, void *tup) -{ - DatumTuple *tuple = (DatumTuple *) tup; - - if (tuple->isNull || state->datumTypeByVal) - return (unsigned int) sizeof(DatumTuple); - else - { - int datalen = state->datumTypeLen; - int tuplelen; - - if (datalen == -1) /* variable length type? */ - datalen = VARSIZE((struct varlena *) DatumGetPointer(tuple->val)); - tuplelen = datalen + MAXALIGN(sizeof(DatumTuple)); - return (unsigned int) tuplelen; - } -} - /* * This routine selects an appropriate sorting function to implement diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index ec9b7d8ce7a..20af54f36c0 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -26,7 +26,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplestore.c,v 1.6 2002/06/20 20:29:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplestore.c,v 1.7 2002/08/12 00:36:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -154,30 +154,15 @@ struct Tuplestorestate * * NOTES about memory consumption calculations: * - * We count space requested for tuples against the maxKBytes limit. - * Fixed-size space (primarily the BufFile I/O buffer) is not - * counted, nor do we count the variable-size memtuples array. - * (Even though that could grow pretty large, it should be small compared - * to the tuples proper, so this is not unreasonable.) + * We count space allocated for tuples against the maxKBytes limit, + * plus the space used by the variable-size array memtuples. + * Fixed-size space (primarily the BufFile I/O buffer) is not counted. * - * The major deficiency in this approach is that it ignores palloc overhead. - * The memory space actually allocated for a palloc chunk is always more - * than the request size, and could be considerably more (as much as 2X - * larger, in the current aset.c implementation). So the space used could - * be considerably more than maxKBytes says. - * - * One way to fix this is to add a memory management function that, given - * a pointer to a palloc'd chunk, returns the actual space consumed by the - * chunk. This would be very easy in the current aset.c module, but I'm - * hesitant to do it because it might be unpleasant to support in future - * implementations of memory management. (For example, a direct - * implementation of palloc as malloc could not support such a function - * portably.) - * - * A cruder answer is just to apply a fudge factor, say by initializing - * availMem to only three-quarters of what maxKBytes indicates. This is - * probably the right answer if anyone complains that maxKBytes is not being - * obeyed very faithfully. + * Note that we count actual space used (as shown by GetMemoryChunkSpace) + * rather than the originally-requested size. This is important since + * palloc can add substantial overhead. It's not a complete answer since + * we won't count any wasted space in palloc allocation blocks, but it's + * a lot better than what we were doing before 7.3. * *-------------------- */ @@ -228,6 +213,8 @@ tuplestore_begin_common(bool randomAccess, int maxKBytes) state->memtupsize = 1; /* won't really need any space */ state->memtuples = (void **) palloc(state->memtupsize * sizeof(void *)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); + return state; } @@ -286,10 +273,12 @@ tuplestore_puttuple(Tuplestorestate *state, void *tuple) if (state->memtupcount >= state->memtupsize) { /* Grow the array as needed. */ + FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); state->memtupsize *= 2; state->memtuples = (void **) repalloc(state->memtuples, state->memtupsize * sizeof(void *)); + USEMEM(state, GetMemoryChunkSpace(state->memtuples)); } state->memtuples[state->memtupcount++] = tuple; @@ -631,8 +620,9 @@ copytup_heap(Tuplestorestate *state, void *tup) { HeapTuple tuple = (HeapTuple) tup; - USEMEM(state, HEAPTUPLESIZE + tuple->t_len); - return (void *) heap_copytuple(tuple); + tuple = heap_copytuple(tuple); + USEMEM(state, GetMemoryChunkSpace(tuple)); + return (void *) tuple; } /* @@ -657,7 +647,7 @@ writetup_heap(Tuplestorestate *state, void *tup) sizeof(tuplen)) != sizeof(tuplen)) elog(ERROR, "tuplestore: write failed"); - FREEMEM(state, HEAPTUPLESIZE + tuple->t_len); + FREEMEM(state, GetMemoryChunkSpace(tuple)); heap_freetuple(tuple); } @@ -667,7 +657,7 @@ readtup_heap(Tuplestorestate *state, unsigned int len) unsigned int tuplen = len - sizeof(unsigned int) + HEAPTUPLESIZE; HeapTuple tuple = (HeapTuple) palloc(tuplen); - USEMEM(state, tuplen); + USEMEM(state, GetMemoryChunkSpace(tuple)); /* reconstruct the HeapTupleData portion */ tuple->t_len = len - sizeof(unsigned int); ItemPointerSetInvalid(&(tuple->t_self)); diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h index 50ffcc0a742..9297db5e978 100644 --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: memnodes.h,v 1.24 2002/06/20 20:29:50 momjian Exp $ + * $Id: memnodes.h,v 1.25 2002/08/12 00:36:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,10 +42,11 @@ typedef struct MemoryContextMethods void (*init) (MemoryContext context); void (*reset) (MemoryContext context); void (*delete) (MemoryContext context); + Size (*get_chunk_space) (MemoryContext context, void *pointer); + void (*stats) (MemoryContext context); #ifdef MEMORY_CONTEXT_CHECKING void (*check) (MemoryContext context); #endif - void (*stats) (MemoryContext context); } MemoryContextMethods; diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index 5e60c52fadd..771618ae56e 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: memutils.h,v 1.46 2002/06/20 20:29:53 momjian Exp $ + * $Id: memutils.h,v 1.47 2002/08/12 00:36:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,8 +82,11 @@ extern void MemoryContextDelete(MemoryContext context); extern void MemoryContextResetChildren(MemoryContext context); extern void MemoryContextDeleteChildren(MemoryContext context); extern void MemoryContextResetAndDeleteChildren(MemoryContext context); +extern Size GetMemoryChunkSpace(void *pointer); extern void MemoryContextStats(MemoryContext context); +#ifdef MEMORY_CONTEXT_CHECKING extern void MemoryContextCheck(MemoryContext context); +#endif extern bool MemoryContextContains(MemoryContext context, void *pointer); /* |