]> granicus.if.org Git - postgresql/commitdiff
Short-circuit AllocSetReset if nothing has been palloc'd in the memory
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 1 Sep 2005 18:15:42 +0000 (18:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 1 Sep 2005 18:15:42 +0000 (18:15 +0000)
context since the previous AllocSetReset.  Original patch by Atsushi Ogawa,
editorialized on a little bit by Tom Lane.

src/backend/utils/mmgr/aset.c

index de56a2dc0101b6e7320e57152ca5874c66311b39..6c1b5f390da6c88bb7396f6a545fc406bb7c264a 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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:
  *     This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -123,6 +123,12 @@ typedef void *AllocPointer;
 
 /*
  * 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
 {
@@ -130,6 +136,7 @@ typedef struct AllocSetContext
        /* Info about storage allocated in this context: */
        AllocBlock      blocks;                 /* head of list of blocks in this set */
        AllocChunk      freelist[ALLOCSET_NUM_FREELISTS];               /* free chunk lists */
+       bool            isReset;                /* T = no space alloced since last reset */
        /* Allocation parameters for this context: */
        Size            initBlockSize;  /* initial block size */
        Size            maxBlockSize;   /* maximum block size */
@@ -347,6 +354,8 @@ AllocSetContextCreate(MemoryContext parent,
                context->keeper = block;
        }
 
+       context->isReset = true;
+
        return (MemoryContext) context;
 }
 
@@ -386,26 +395,28 @@ static void
 AllocSetReset(MemoryContext context)
 {
        AllocSet        set = (AllocSet) context;
-       AllocBlock      block = set->blocks;
+       AllocBlock      block;
 
        AssertArg(AllocSetIsValid(set));
 
+       /* Nothing to do if no pallocs since startup or last reset */
+       if (set->isReset)
+               return;
+
 #ifdef MEMORY_CONTEXT_CHECKING
        /* Check for corruption and leaks before freeing */
        AllocSetCheck(context);
 #endif
 
-       /* Nothing to do if context has never contained any data */
-       if (block == NULL)
-               return;
-
        /* Clear chunk freelists */
        MemSetAligned(set->freelist, 0, sizeof(set->freelist));
 
+       block = set->blocks;
+
        /* New blocks list is either empty or just the keeper block */
        set->blocks = set->keeper;
 
-       do
+       while (block != NULL)
        {
                AllocBlock      next = block->next;
 
@@ -432,7 +443,8 @@ AllocSetReset(MemoryContext context)
                }
                block = next;
        }
-       while (block != NULL);
+
+       set->isReset = true;
 }
 
 /*
@@ -538,6 +550,8 @@ AllocSetAlloc(MemoryContext context, Size size)
                        set->blocks = block;
                }
 
+               set->isReset = false;
+
                AllocAllocInfo(set, chunk);
                return AllocChunkGetPointer(chunk);
        }
@@ -576,6 +590,9 @@ AllocSetAlloc(MemoryContext context, Size size)
                        ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif
 
+               /* isReset must be false already */
+               Assert(!set->isReset);
+
                AllocAllocInfo(set, chunk);
                return AllocChunkGetPointer(chunk);
        }
@@ -748,6 +765,8 @@ AllocSetAlloc(MemoryContext context, Size size)
                ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif
 
+       set->isReset = false;
+
        AllocAllocInfo(set, chunk);
        return AllocChunkGetPointer(chunk);
 }
@@ -846,6 +865,9 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
                                 set->header.name, chunk);
 #endif
 
+       /* isReset must be false already */
+       Assert(!set->isReset);
+
        /*
         * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
         * allocated area already is >= the new size.  (In particular, we
@@ -1009,12 +1031,12 @@ AllocSetIsEmpty(MemoryContext context)
        AllocSet        set = (AllocSet) context;
 
        /*
-        * For now, we say "empty" only if the context never contained any
-        * space at all.  We could examine the freelists to determine if all
-        * space has been freed, but it's not really worth the trouble for
-        * present uses of this functionality.
+        * For now, we say "empty" only if the context is new or just reset.
+        * We could examine the freelists to determine if all space has been
+        * freed, but it's not really worth the trouble for present uses of
+        * this functionality.
         */
-       if (set->blocks == NULL)
+       if (set->isReset)
                return true;
        return false;
 }