Commit ab5b4e2f authored by Tom Lane's avatar Tom Lane

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.
parent f3f45c87
...@@ -11,7 +11,7 @@ ...@@ -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 = { ...@@ -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 = { ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment