*** ./src/backend/utils/mmgr/aset.c.orig Sat May 14 01:06:03 2005 --- ./src/backend/utils/mmgr/aset.c Sat May 14 02:13:21 2005 *************** *** 231,236 **** --- 231,262 ---- }; + /* + * These functions fast version of the MemoryContext API. + */ + static void *FastAllocSetAlloc(MemoryContext context, Size size); + static void FastAllocSetFree(MemoryContext context, void *pointer); + static void *FastAllocSetRealloc(MemoryContext context, void *pointer, Size size); + static void FastAllocSetReset(MemoryContext context); + + /* + * This is the virtual function table for AllocSet contexts. (Fast mode) + */ + static MemoryContextMethods FastAllocSetMethods = { + FastAllocSetAlloc, + FastAllocSetFree, + FastAllocSetRealloc, + AllocSetInit, + FastAllocSetReset, + AllocSetDelete, + AllocSetGetChunkSpace, + AllocSetIsEmpty, + AllocSetStats + #ifdef MEMORY_CONTEXT_CHECKING + ,AllocSetCheck + #endif + }; + /* ---------- * Debug macros * ---------- *************** *** 299,308 **** { AllocSet context; ! /* Do the type-independent part of context creation */ context = (AllocSet) MemoryContextCreate(T_AllocSetContext, sizeof(AllocSetContext), ! &AllocSetMethods, parent, name); --- 325,337 ---- { AllocSet context; ! /* ! * Do the type-independent part of context creation ! * It initializes fast mode. ! */ context = (AllocSet) MemoryContextCreate(T_AllocSetContext, sizeof(AllocSetContext), ! &FastAllocSetMethods, parent, name); *************** *** 427,432 **** --- 456,466 ---- } block = next; } + + /* + * Changed to the fast mode. + */ + context->methods = &FastAllocSetMethods; } /* *************** *** 1144,1146 **** --- 1178,1364 ---- } #endif /* MEMORY_CONTEXT_CHECKING */ + + /* + * FastAllocSetReset + * This function is faster version of AllocSetReset. When this + * function is called, the freelist is not used. And the + * block list should be null or keeper block only. + */ + static void + FastAllocSetReset(MemoryContext context) + { + AllocSet set = (AllocSet) context; + AllocBlock block = set->blocks; + + AssertArg(AllocSetIsValid(set)); + + #ifdef MEMORY_CONTEXT_CHECKING + /* Check for corruption and leaks before freeing */ + AllocSetCheck(context); + #endif + + if(block != NULL) + { + /* Reset the block, but don't return it to malloc */ + char *datastart = ((char *) block) + ALLOC_BLOCKHDRSZ; + + Assert(block == set->keeper && block->next == NULL); + + #ifdef CLOBBER_FREED_MEMORY + /* Wipe freed memory for debugging purposes */ + memset(datastart, 0x7F, block->freeptr - datastart); + #endif + block->freeptr = datastart; + block->next = NULL; + } + } + + /* + * FastAllocSetAlloc + * This function is faster version of AllocSetAlloc. When it is + * possible to allocate memory from the keeper block, it's allocated. + * Otherwise the context changed to the normal mode. + * + */ + static void * + FastAllocSetAlloc(MemoryContext context, Size size) + { + AllocSet set = (AllocSet) context; + AllocBlock block; + AllocChunk chunk; + int fidx; + Size chunk_size; + Size blksize; + + AssertArg(AllocSetIsValid(set)); + + /* + * If requested size exceeds maximum for chunks, this context + * changed to the normal mode. + */ + if (size > ALLOC_CHUNK_LIMIT) + { + context->methods = &AllocSetMethods; + return AllocSetAlloc(context, size); + } + + /* + * Request is small enough to be treated as a chunk. + * Choose the actual chunk size to allocate. + */ + fidx = AllocSetFreeIndex(size); + chunk_size = 1 << (fidx + ALLOC_MINBITS); + Assert(chunk_size >= size); + + if ((block = set->blocks) != NULL) + { + Size availspace = block->endptr - block->freeptr; + + /* + * When the avail space of first block is insufficient, this context + * changed to the normal mode. + */ + if (availspace < (chunk_size + ALLOC_CHUNKHDRSZ)) + { + context->methods = &AllocSetMethods; + return AllocSetAlloc(context, size); + } + } else { + /* + * Time to create a first block of context. + */ + Size required_size; + + /* First block of the alloc set, use initBlockSize */ + blksize = set->initBlockSize; + + /* + * If requied_size larger than initBlockSize, this context + * context changed to the normal mode. + */ + required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ; + if (blksize < required_size) { + context->methods = &AllocSetMethods; + return AllocSetAlloc(context, size); + } + + /* Try to allocate it */ + block = (AllocBlock) malloc(blksize); + + if (block == NULL) + { + MemoryContextStats(TopMemoryContext); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("Failed on request of size %lu.", + (unsigned long) size))); + } + + block->aset = set; + block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ; + block->endptr = ((char *) block) + blksize; + + /* + * make first block to the "keeper" block. + */ + Assert(set->keeper == NULL); + set->keeper = block; + + Assert(set->blocks == NULL); + block->next = set->blocks; + set->blocks = block; + } + + /* + * OK, do the allocation + */ + chunk = (AllocChunk) (block->freeptr); + + block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ); + Assert(block->freeptr <= block->endptr); + + chunk->aset = (void *) set; + chunk->size = chunk_size; + #ifdef MEMORY_CONTEXT_CHECKING + chunk->requested_size = size; + /* set mark to catch clobber of "unused" space */ + if (size < chunk->size) + ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E; + #endif + + AllocAllocInfo(set, chunk); + return AllocChunkGetPointer(chunk); + } + + /* + * FastAllocSetFree + * This function just hooks the call of pfree. When this function + * is called, the context is changed to the normal mode. + */ + static void + FastAllocSetFree(MemoryContext context, void *pointer) + { + /* + * Changed to the normal mode. + */ + context->methods = &AllocSetMethods; + return AllocSetFree(context, pointer); + } + + /* + * FastAllocSetRealloc + * This function just hooks the call of repalloc. When this function + * is called, the context is changed to the normal mode. + */ + static void * + FastAllocSetRealloc(MemoryContext context, void *pointer, Size size) + { + /* + * Changed to the normal mode. + */ + context->methods = &AllocSetMethods; + return AllocSetRealloc(context, pointer, size); + } +