From 728b0aa290ce2bc1639563e2dfd05fe6d8d6e7f2 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
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 5c0cf307453..c78008824b5 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);
-- 
GitLab