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: