Re: memory allocation and powers of two - Mailing list pgsql-hackers

From Tom Lane
Subject Re: memory allocation and powers of two
Date
Msg-id 21049.1063492214@sss.pgh.pa.us
Whole thread Raw
In response to memory allocation and powers of two  (David Schultz <dschultz@uclink.Berkeley.EDU>)
Responses Re: memory allocation and powers of two
List pgsql-hackers
David Schultz <dschultz@uclink.Berkeley.EDU> writes:
> While looking into a block size mismatch problem between
> Postgresql and FreeBSD's FFS, I noticed that postgresql is making
> some rather odd-sized requests to malloc(3): 0x2034, 0x2020,
> 0x4018, 0x8018, etc.  Most malloc(3) implementations round large
> allocations up to a multiple of a large power of 2---often the
> hardware page size, so this is a pathological case for those
> allocators.

After looking more closely I saw that there were some corner cases where
aset.c would unnecessarily switch from the intended power-of-two block
sizes to non-power-of-two sizes.  I've applied the attached fix.
        regards, tom lane

*** src/backend/utils/mmgr/aset.c.orig    Sun Aug  3 23:01:13 2003
--- src/backend/utils/mmgr/aset.c    Sat Sep 13 18:20:48 2003
***************
*** 650,681 ****         }         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.              */
!             if (blksize < set->initBlockSize)
!                 blksize = set->initBlockSize;
!             else
!             {
!                 /* Crank it up, but not past max */                 blksize <<= 1;
!                 if (blksize > set->maxBlockSize)
!                     blksize = set->maxBlockSize;
!             }         }          /*          * If initBlockSize is less than ALLOC_CHUNK_LIMIT, we could need
!          * more space...          */         required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
!         if (blksize < required_size)
!             blksize = required_size;          /* Try to allocate it */         block = (AllocBlock) malloc(blksize);
--- 650,678 ----         }         else         {             /*
!              * 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.)              */
!             Size    pblksize = set->blocks->endptr - ((char *) set->blocks);
! 
!             blksize = set->initBlockSize;
!             while (blksize <= pblksize)                 blksize <<= 1;
!             if (blksize > set->maxBlockSize)
!                 blksize = set->maxBlockSize;         }          /*          * If initBlockSize is less than
ALLOC_CHUNK_LIMIT,we could need
 
!          * more space... but try to keep it a power of 2.          */         required_size = chunk_size +
ALLOC_BLOCKHDRSZ+ ALLOC_CHUNKHDRSZ;
 
!         while (blksize < required_size)
!             blksize <<= 1;          /* Try to allocate it */         block = (AllocBlock) malloc(blksize);


pgsql-hackers by date:

Previous
From: Larry Rosenman
Date:
Subject: Link.shared help
Next
From: "Gaetano Mendola"
Date:
Subject: Re: Problem with function permission test in a view