From 728b0aa290ce2bc1639563e2dfd05fe6d8d6e7f2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 23 Jan 2001 01:01:36 +0000 Subject: [PATCH] Improve realloc() per idea from Karel Zak --- if chunk to be enlarged is at end of its block, maybe we can enlarge it in-place. --- src/backend/utils/mmgr/aset.c | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 5c0cf30745..c78008824b 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.37 2001/01/12 21:54:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.38 2001/01/23 01:01:36 tgl Exp $ * * NOTE: * This is a new (Feb. 05, 1999) implementation of the allocation set @@ -879,10 +879,60 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) } else { + /* + * Small-chunk case. If the chunk is the last one in its block, + * there might be enough free space after it that we can just + * enlarge the chunk in-place. It's relatively painful to find + * the containing block in the general case, but we can detect + * last-ness quite cheaply for the typical case where the chunk + * is in the active (topmost) allocation block. (At least with + * the regression tests and code as of 1/2001, realloc'ing the last + * chunk of a non-topmost block hardly ever happens, so it's not + * worth scanning the block list to catch that case.) + * + * NOTE: must be careful not to create a chunk of a size that + * AllocSetAlloc would not create, else we'll get confused later. + */ + AllocPointer newPointer; + + if (size <= ALLOC_CHUNK_LIMIT) + { + AllocBlock block = set->blocks; + char *chunk_end; + + chunk_end = (char *) chunk + (oldsize + ALLOC_CHUNKHDRSZ); + if (chunk_end == block->freeptr) + { + /* OK, it's last in block ... is there room? */ + Size freespace = block->endptr - block->freeptr; + int fidx; + Size newsize; + Size delta; + + fidx = AllocSetFreeIndex(size); + newsize = 1 << (fidx + ALLOC_MINBITS); + Assert(newsize >= oldsize); + delta = newsize - oldsize; + if (freespace >= delta) + { + /* Yes, so just enlarge the chunk. */ + block->freeptr += delta; + chunk->size += delta; +#ifdef MEMORY_CONTEXT_CHECKING + chunk->requested_size = size; + /* set mark to catch clobber of "unused" space */ + if (size < chunk->size) + ((char *) pointer)[size] = 0x7E; +#endif + return pointer; + } + } + } + /* Normal small-chunk case: just do it by brute force. */ /* allocate new chunk */ - AllocPointer newPointer = AllocSetAlloc((MemoryContext) set, size); + newPointer = AllocSetAlloc((MemoryContext) set, size); /* transfer existing data (certain to fit) */ memcpy(newPointer, pointer, oldsize); -- 2.40.0