From: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
---|---|
To: | David Schultz <dschultz(at)uclink(dot)Berkeley(dot)EDU> |
Cc: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: memory allocation and powers of two |
Date: | 2003-09-13 22:30:14 |
Message-ID: | 21049.1063492214@sss.pgh.pa.us |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
David Schultz <dschultz(at)uclink(dot)Berkeley(dot)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);
From | Date | Subject | |
---|---|---|---|
Next Message | Gaetano Mendola | 2003-09-14 00:07:10 | Re: Problem with function permission test in a view |
Previous Message | Miko O'Sullivan | 2003-09-13 21:14:39 | Re: massive quotes? |