Commit a635ab46 authored by Tom Lane's avatar Tom Lane

Short-circuit AllocSetReset if nothing has been palloc'd in the memory

context since the previous AllocSetReset.  Original patch by Atsushi Ogawa,
editorialized on a little bit by Tom Lane.
parent 91a21b53
...@@ -11,7 +11,7 @@ ...@@ -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
* $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.62 2005/06/04 22:57:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.63 2005/09/01 18:15:42 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
...@@ -123,6 +123,12 @@ typedef void *AllocPointer; ...@@ -123,6 +123,12 @@ typedef void *AllocPointer;
/* /*
* AllocSetContext is our standard implementation of MemoryContext. * AllocSetContext is our standard implementation of MemoryContext.
*
* Note: isReset means there is nothing for AllocSetReset to do. This is
* different from the aset being physically empty (empty blocks list) because
* we may still have a keeper block. It's also different from the set being
* logically empty, because we don't attempt to detect pfree'ing the last
* active chunk.
*/ */
typedef struct AllocSetContext typedef struct AllocSetContext
{ {
...@@ -130,6 +136,7 @@ typedef struct AllocSetContext ...@@ -130,6 +136,7 @@ typedef struct AllocSetContext
/* Info about storage allocated in this context: */ /* Info about storage allocated in this context: */
AllocBlock blocks; /* head of list of blocks in this set */ AllocBlock blocks; /* head of list of blocks in this set */
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */ AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
bool isReset; /* T = no space alloced since last reset */
/* Allocation parameters for this context: */ /* Allocation parameters for this context: */
Size initBlockSize; /* initial block size */ Size initBlockSize; /* initial block size */
Size maxBlockSize; /* maximum block size */ Size maxBlockSize; /* maximum block size */
...@@ -347,6 +354,8 @@ AllocSetContextCreate(MemoryContext parent, ...@@ -347,6 +354,8 @@ AllocSetContextCreate(MemoryContext parent,
context->keeper = block; context->keeper = block;
} }
context->isReset = true;
return (MemoryContext) context; return (MemoryContext) context;
} }
...@@ -386,26 +395,28 @@ static void ...@@ -386,26 +395,28 @@ static void
AllocSetReset(MemoryContext context) AllocSetReset(MemoryContext context)
{ {
AllocSet set = (AllocSet) context; AllocSet set = (AllocSet) context;
AllocBlock block = set->blocks; AllocBlock block;
AssertArg(AllocSetIsValid(set)); AssertArg(AllocSetIsValid(set));
/* Nothing to do if no pallocs since startup or last reset */
if (set->isReset)
return;
#ifdef MEMORY_CONTEXT_CHECKING #ifdef MEMORY_CONTEXT_CHECKING
/* Check for corruption and leaks before freeing */ /* Check for corruption and leaks before freeing */
AllocSetCheck(context); AllocSetCheck(context);
#endif #endif
/* Nothing to do if context has never contained any data */
if (block == NULL)
return;
/* Clear chunk freelists */ /* Clear chunk freelists */
MemSetAligned(set->freelist, 0, sizeof(set->freelist)); MemSetAligned(set->freelist, 0, sizeof(set->freelist));
block = set->blocks;
/* New blocks list is either empty or just the keeper block */ /* New blocks list is either empty or just the keeper block */
set->blocks = set->keeper; set->blocks = set->keeper;
do while (block != NULL)
{ {
AllocBlock next = block->next; AllocBlock next = block->next;
...@@ -432,7 +443,8 @@ AllocSetReset(MemoryContext context) ...@@ -432,7 +443,8 @@ AllocSetReset(MemoryContext context)
} }
block = next; block = next;
} }
while (block != NULL);
set->isReset = true;
} }
/* /*
...@@ -538,6 +550,8 @@ AllocSetAlloc(MemoryContext context, Size size) ...@@ -538,6 +550,8 @@ AllocSetAlloc(MemoryContext context, Size size)
set->blocks = block; set->blocks = block;
} }
set->isReset = false;
AllocAllocInfo(set, chunk); AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk); return AllocChunkGetPointer(chunk);
} }
...@@ -576,6 +590,9 @@ AllocSetAlloc(MemoryContext context, Size size) ...@@ -576,6 +590,9 @@ AllocSetAlloc(MemoryContext context, Size size)
((char *) AllocChunkGetPointer(chunk))[size] = 0x7E; ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
#endif #endif
/* isReset must be false already */
Assert(!set->isReset);
AllocAllocInfo(set, chunk); AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk); return AllocChunkGetPointer(chunk);
} }
...@@ -748,6 +765,8 @@ AllocSetAlloc(MemoryContext context, Size size) ...@@ -748,6 +765,8 @@ AllocSetAlloc(MemoryContext context, Size size)
((char *) AllocChunkGetPointer(chunk))[size] = 0x7E; ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
#endif #endif
set->isReset = false;
AllocAllocInfo(set, chunk); AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk); return AllocChunkGetPointer(chunk);
} }
...@@ -846,6 +865,9 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) ...@@ -846,6 +865,9 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
set->header.name, chunk); set->header.name, chunk);
#endif #endif
/* isReset must be false already */
Assert(!set->isReset);
/* /*
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
* allocated area already is >= the new size. (In particular, we * allocated area already is >= the new size. (In particular, we
...@@ -1009,12 +1031,12 @@ AllocSetIsEmpty(MemoryContext context) ...@@ -1009,12 +1031,12 @@ AllocSetIsEmpty(MemoryContext context)
AllocSet set = (AllocSet) context; AllocSet set = (AllocSet) context;
/* /*
* For now, we say "empty" only if the context never contained any * For now, we say "empty" only if the context is new or just reset.
* space at all. We could examine the freelists to determine if all * We could examine the freelists to determine if all space has been
* space has been freed, but it's not really worth the trouble for * freed, but it's not really worth the trouble for present uses of
* present uses of this functionality. * this functionality.
*/ */
if (set->blocks == NULL) if (set->isReset)
return true; return true;
return false; return false;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment