diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 0135ba0e0b3..5e97ebe8969 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 - * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.69 2006/11/08 19:27:24 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.70 2006/12/27 22:30:48 tgl Exp $ * * NOTE: * This is a new (Feb. 05, 1999) implementation of the allocation set @@ -141,6 +141,7 @@ typedef struct AllocSetContext Size initBlockSize; /* initial block size */ Size maxBlockSize; /* maximum block size */ Size nextBlockSize; /* next block size to allocate */ + Size allocChunkLimit; /* effective chunk size limit */ AllocBlock keeper; /* if not NULL, keep this block over resets */ } AllocSetContext; @@ -328,6 +329,20 @@ AllocSetContextCreate(MemoryContext parent, context->maxBlockSize = maxBlockSize; context->nextBlockSize = initBlockSize; + /* + * Compute the allocation chunk size limit for this context. It can't + * be more than ALLOC_CHUNK_LIMIT because of the fixed number of + * freelists. If maxBlockSize is small then requests exceeding the + * maxBlockSize should be treated as large chunks, too. We have to + * have allocChunkLimit a power of two, because the requested and + * actually-allocated sizes of any chunk must be on the same side of + * the limit, else we get confused about whether the chunk is "big". + */ + context->allocChunkLimit = ALLOC_CHUNK_LIMIT; + while (context->allocChunkLimit > + (Size) (maxBlockSize - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ)) + context->allocChunkLimit >>= 1; + /* * Grab always-allocated space, if requested */ @@ -512,7 +527,7 @@ AllocSetAlloc(MemoryContext context, Size size) * If requested size exceeds maximum for chunks, allocate an entire block * for this request. */ - if (size > ALLOC_CHUNK_LIMIT) + if (size > set->allocChunkLimit) { chunk_size = MAXALIGN(size); blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ; @@ -775,7 +790,7 @@ AllocSetFree(MemoryContext context, void *pointer) set->header.name, chunk); #endif - if (chunk->size > ALLOC_CHUNK_LIMIT) + if (chunk->size > set->allocChunkLimit) { /* * Big chunks are certain to have been allocated as single-chunk @@ -868,7 +883,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) return pointer; } - if (oldsize > ALLOC_CHUNK_LIMIT) + if (oldsize > set->allocChunkLimit) { /* * The chunk must have been allocated as a single-chunk block. Find @@ -943,7 +958,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) */ AllocPointer newPointer; - if (size <= ALLOC_CHUNK_LIMIT) + if (size <= set->allocChunkLimit) { AllocBlock block = set->blocks; char *chunk_end; @@ -1122,7 +1137,7 @@ AllocSetCheck(MemoryContext context) name, (unsigned long) chsize, chunk, block); /* single-chunk block? */ - if (chsize > ALLOC_CHUNK_LIMIT && + if (chsize > set->allocChunkLimit && chsize + ALLOC_CHUNKHDRSZ != blk_used) elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p", name, chunk, block);