mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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.
This commit is contained in:
parent
c0bb21b369
commit
728b0aa290
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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:
|
* NOTE:
|
||||||
* This is a new (Feb. 05, 1999) implementation of the allocation set
|
* This is a new (Feb. 05, 1999) implementation of the allocation set
|
||||||
@ -879,10 +879,60 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|||||||
}
|
}
|
||||||
else
|
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. */
|
/* Normal small-chunk case: just do it by brute force. */
|
||||||
|
|
||||||
/* allocate new chunk */
|
/* allocate new chunk */
|
||||||
AllocPointer newPointer = AllocSetAlloc((MemoryContext) set, size);
|
newPointer = AllocSetAlloc((MemoryContext) set, size);
|
||||||
|
|
||||||
/* transfer existing data (certain to fit) */
|
/* transfer existing data (certain to fit) */
|
||||||
memcpy(newPointer, pointer, oldsize);
|
memcpy(newPointer, pointer, oldsize);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user