]> granicus.if.org Git - postgresql/commitdiff
Avoid corner cases where aset.c would unnecessarily make malloc()
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 13 Sep 2003 22:25:38 +0000 (22:25 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 13 Sep 2003 22:25:38 +0000 (22:25 +0000)
requests of sizes that aren't powers of 2.  Per observation from
David Schultz, 28-Aug.

src/backend/utils/mmgr/aset.c

index fddcad7a29bdeae8a96891a343fb39da9152593a..b36596734d746d30b7afcc6040a3d49ec252cd80 100644 (file)
@@ -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.52 2003/08/04 02:40:08 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.53 2003/09/13 22:25:38 tgl Exp $
  *
  * NOTE:
  *     This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -650,32 +650,29 @@ AllocSetAlloc(MemoryContext context, Size size)
                }
                else
                {
-                       /* Get size of prior block */
-                       blksize = set->blocks->endptr - ((char *) set->blocks);
-
                        /*
-                        * Special case: if very first allocation was for a large
-                        * chunk (or we have a small "keeper" block), could have an
-                        * undersized top block.  Do something reasonable.
+                        * Use first power of 2 that is larger than previous block,
+                        * but not more than the allowed limit.  (We don't simply double
+                        * the prior block size, because in some cases this could be a
+                        * funny size, eg if very first allocation was for an odd-sized
+                        * large chunk.)
                         */
-                       if (blksize < set->initBlockSize)
-                               blksize = set->initBlockSize;
-                       else
-                       {
-                               /* Crank it up, but not past max */
+                       Size    pblksize = set->blocks->endptr - ((char *) set->blocks);
+
+                       blksize = set->initBlockSize;
+                       while (blksize <= pblksize)
                                blksize <<= 1;
-                               if (blksize > set->maxBlockSize)
-                                       blksize = set->maxBlockSize;
-                       }
+                       if (blksize > set->maxBlockSize)
+                               blksize = set->maxBlockSize;
                }
 
                /*
                 * If initBlockSize is less than ALLOC_CHUNK_LIMIT, we could need
-                * more space...
+                * more space... but try to keep it a power of 2.
                 */
                required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
-               if (blksize < required_size)
-                       blksize = required_size;
+               while (blksize < required_size)
+                       blksize <<= 1;
 
                /* Try to allocate it */
                block = (AllocBlock) malloc(blksize);