Speed up AllocSetFreeIndex, which is a significant cost in palloc and pfree,
by using a lookup table instead of a naive shift-and-count loop. Based on code originally posted by Sean Eron Anderson at http://graphics.stanford.edu/%7eseander/bithacks.html. Greg Stark did the research and benchmarking to show that this is what we should use. Jeremy Kerr first noticed that this is a hotspot that could be optimized, though we ended up not using his suggestion of platform-specific bit-searching code.
This commit is contained in:
parent
f3f45c87d2
commit
ab5b4e2f9e
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.79 2009/06/11 14:49:06 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.80 2009/07/21 19:53:12 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTE:
|
* NOTE:
|
||||||
* This is a new (Feb. 05, 1999) implementation of the allocation set
|
* This is a new (Feb. 05, 1999) implementation of the allocation set
|
||||||
@ -238,6 +238,17 @@ static MemoryContextMethods AllocSetMethods = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table for AllocSetFreeIndex
|
||||||
|
*/
|
||||||
|
#define LT16(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
|
||||||
|
|
||||||
|
static const unsigned char LogTable256[256] =
|
||||||
|
{
|
||||||
|
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
LT16(5), LT16(6), LT16(6), LT16(7), LT16(7), LT16(7), LT16(7),
|
||||||
|
LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8)
|
||||||
|
};
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Debug macros
|
* Debug macros
|
||||||
@ -266,18 +277,30 @@ static MemoryContextMethods AllocSetMethods = {
|
|||||||
static inline int
|
static inline int
|
||||||
AllocSetFreeIndex(Size size)
|
AllocSetFreeIndex(Size size)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx;
|
||||||
|
unsigned int t,
|
||||||
|
tsize;
|
||||||
|
|
||||||
if (size > 0)
|
if (size > (1 << ALLOC_MINBITS))
|
||||||
{
|
{
|
||||||
size = (size - 1) >> ALLOC_MINBITS;
|
tsize = (size - 1) >> ALLOC_MINBITS;
|
||||||
while (size != 0)
|
|
||||||
{
|
/*
|
||||||
idx++;
|
* At this point we need to obtain log2(tsize)+1, ie, the number
|
||||||
size >>= 1;
|
* of not-all-zero bits at the right. We used to do this with a
|
||||||
}
|
* shift-and-count loop, but this function is enough of a hotspot
|
||||||
|
* to justify micro-optimization effort. The best approach seems
|
||||||
|
* to be to use a lookup table. Note that this code assumes that
|
||||||
|
* ALLOCSET_NUM_FREELISTS <= 17, since we only cope with two bytes
|
||||||
|
* of the tsize value.
|
||||||
|
*/
|
||||||
|
t = tsize >> 8;
|
||||||
|
idx = t ? LogTable256[t] + 8 : LogTable256[tsize];
|
||||||
|
|
||||||
Assert(idx < ALLOCSET_NUM_FREELISTS);
|
Assert(idx < ALLOCSET_NUM_FREELISTS);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
idx = 0;
|
||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user