99 #define SH_MAKE_PREFIX(a) CppConcat(a,_)
100 #define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX),name)
101 #define SH_MAKE_NAME_(a,b) CppConcat(a,b)
106 #define SH_TYPE SH_MAKE_NAME(hash)
107 #define SH_STATUS SH_MAKE_NAME(status)
108 #define SH_STATUS_EMPTY SH_MAKE_NAME(SH_EMPTY)
109 #define SH_STATUS_IN_USE SH_MAKE_NAME(SH_IN_USE)
110 #define SH_ITERATOR SH_MAKE_NAME(iterator)
113 #define SH_CREATE SH_MAKE_NAME(create)
114 #define SH_DESTROY SH_MAKE_NAME(destroy)
115 #define SH_RESET SH_MAKE_NAME(reset)
116 #define SH_INSERT SH_MAKE_NAME(insert)
117 #define SH_INSERT_HASH SH_MAKE_NAME(insert_hash)
118 #define SH_DELETE_ITEM SH_MAKE_NAME(delete_item)
119 #define SH_DELETE SH_MAKE_NAME(delete)
120 #define SH_LOOKUP SH_MAKE_NAME(lookup)
121 #define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash)
122 #define SH_GROW SH_MAKE_NAME(grow)
123 #define SH_START_ITERATE SH_MAKE_NAME(start_iterate)
124 #define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at)
125 #define SH_ITERATE SH_MAKE_NAME(iterate)
126 #define SH_ALLOCATE SH_MAKE_NAME(allocate)
127 #define SH_FREE SH_MAKE_NAME(free)
128 #define SH_STAT SH_MAKE_NAME(stat)
131 #define SH_COMPUTE_SIZE SH_MAKE_NAME(compute_size)
132 #define SH_UPDATE_PARAMETERS SH_MAKE_NAME(update_parameters)
133 #define SH_NEXT SH_MAKE_NAME(next)
134 #define SH_PREV SH_MAKE_NAME(prev)
135 #define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
136 #define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
137 #define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
138 #define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal)
139 #define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal)
166 #ifndef SH_RAW_ALLOCATOR
189 #ifdef SH_RAW_ALLOCATOR
254 #ifndef SH_RAW_ALLOCATOR
259 #define SH_MAX_SIZE (((uint64) PG_UINT32_MAX) + 1)
262 #ifndef SH_FILLFACTOR
263 #define SH_FILLFACTOR (0.9)
266 #define SH_MAX_FILLFACTOR (0.98)
268 #ifndef SH_GROW_MAX_DIB
269 #define SH_GROW_MAX_DIB 25
272 #ifndef SH_GROW_MAX_MOVE
273 #define SH_GROW_MAX_MOVE 150
275 #ifndef SH_GROW_MIN_FILLFACTOR
277 #define SH_GROW_MIN_FILLFACTOR 0.1
281 #define SH_COMPARE_KEYS(tb, ahash, akey, b) (ahash == SH_GET_HASH(tb, b) && SH_EQUAL(tb, b->SH_KEY, akey))
283 #define SH_COMPARE_KEYS(tb, ahash, akey, b) (SH_EQUAL(tb, b->SH_KEY, akey))
297 #define sh_error(...) pg_fatal(__VA_ARGS__)
298 #define sh_log(...) pg_log_info(__VA_ARGS__)
300 #define sh_error(...) elog(ERROR, __VA_ARGS__)
301 #define sh_log(...) elog(LOG, __VA_ARGS__)
327 sh_error(
"hash table too large");
349 if (tb->
size == SH_MAX_SIZE)
366 curelem = (curelem + 1) & tb->
sizemask;
368 Assert(curelem != startelem);
377 curelem = (curelem - 1) & tb->
sizemask;
379 Assert(curelem != startelem);
388 if (optimal <= bucket)
389 return bucket - optimal;
391 return (tb->
size + bucket) - optimal;
408 #ifndef SH_USE_NONDEFAULT_ALLOCATOR
414 #ifdef SH_RAW_ALLOCATOR
440 #ifdef SH_RAW_ALLOCATOR
451 #ifdef SH_RAW_ALLOCATOR
460 size =
Min((
double) SH_MAX_SIZE, ((
double) nelements) / SH_FILLFACTOR);
496 uint64 oldsize = tb->
size;
504 Assert(oldsize != SH_MAX_SIZE);
505 Assert(oldsize < newsize);
537 for (
i = 0;
i < oldsize;
i++)
560 copyelem = startelem;
561 for (
i = 0;
i < oldsize;
i++)
574 curelem = startelem2;
579 newentry = &newdata[curelem];
586 curelem =
SH_NEXT(tb, curelem, startelem2);
595 if (copyelem >= oldsize)
630 sh_error(
"hash table size exceeded");
672 if (SH_COMPARE_KEYS(tb,
hash,
key, entry))
683 if (insertdist > curdist)
686 uint32 emptyelem = curelem;
695 emptyelem =
SH_NEXT(tb, emptyelem, startelem);
696 emptyentry = &
data[emptyelem];
700 lastentry = emptyentry;
713 if (
unlikely(++emptydist > SH_GROW_MAX_MOVE) &&
714 ((
double) tb->
members / tb->
size) >= SH_GROW_MIN_FILLFACTOR)
728 moveelem = emptyelem;
729 while (moveelem != curelem)
733 moveelem =
SH_PREV(tb, moveelem, startelem);
734 moveentry = &
data[moveelem];
737 lastentry = moveentry;
752 curelem =
SH_NEXT(tb, curelem, startelem);
763 if (
unlikely(insertdist > SH_GROW_MAX_DIB) &&
764 ((
double) tb->
members / tb->
size) >= SH_GROW_MIN_FILLFACTOR)
803 uint32 curelem = startelem;
816 if (SH_COMPARE_KEYS(tb,
hash,
key, entry))
826 curelem =
SH_NEXT(tb, curelem, startelem);
861 uint32 curelem = startelem;
871 SH_COMPARE_KEYS(tb,
hash,
key, entry))
890 curelem =
SH_NEXT(tb, curelem, startelem);
891 curentry = &tb->
data[curelem];
903 if (curoptimal == curelem)
912 lastentry = curentry;
920 curelem =
SH_NEXT(tb, curelem, startelem);
936 curelem = entry - &tb->
data[0];
953 curelem =
SH_NEXT(tb, curelem, startelem);
954 curentry = &tb->
data[curelem];
966 if (curoptimal == curelem)
975 lastentry = curentry;
1004 Assert(startelem < SH_MAX_SIZE);
1010 iter->
cur = startelem;
1074 uint32 max_chain_length = 0;
1075 uint32 total_chain_length = 0;
1076 double avg_chain_length;
1081 uint32 total_collisions = 0;
1082 uint32 max_collisions = 0;
1083 double avg_collisions;
1085 for (
i = 0;
i < tb->
size;
i++)
1092 elem = &tb->
data[
i];
1101 if (dist > max_chain_length)
1102 max_chain_length = dist;
1103 total_chain_length += dist;
1105 collisions[optimal]++;
1108 for (
i = 0;
i < tb->
size;
i++)
1110 uint32 curcoll = collisions[
i];
1117 total_collisions += curcoll;
1118 if (curcoll > max_collisions)
1119 max_collisions = curcoll;
1128 avg_chain_length = ((double) total_chain_length) / tb->
members;
1129 avg_collisions = ((double) total_collisions) / tb->
members;
1134 avg_chain_length = 0;
1138 sh_log(
"size: " UINT64_FORMAT ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, total_collisions: %u, max_collisions: %u, avg_collisions: %f",
1140 total_collisions, max_collisions, avg_collisions);
1150 #undef SH_ELEMENT_TYPE
1156 #undef SH_STORE_HASH
1157 #undef SH_USE_NONDEFAULT_ALLOCATOR
1161 #undef SH_MAKE_PREFIX
1163 #undef SH_MAKE_NAME_
1164 #undef SH_FILLFACTOR
1165 #undef SH_MAX_FILLFACTOR
1166 #undef SH_GROW_MAX_DIB
1167 #undef SH_GROW_MAX_MOVE
1168 #undef SH_GROW_MIN_FILLFACTOR
1174 #undef SH_STATUS_EMPTY
1175 #undef SH_STATUS_IN_USE
1183 #undef SH_INSERT_HASH
1184 #undef SH_DELETE_ITEM
1187 #undef SH_LOOKUP_HASH
1189 #undef SH_START_ITERATE
1190 #undef SH_START_ITERATE_AT
1197 #undef SH_COMPUTE_SIZE
1198 #undef SH_UPDATE_PARAMETERS
1199 #undef SH_COMPARE_KEYS
1200 #undef SH_INITIAL_BUCKET
1203 #undef SH_DISTANCE_FROM_OPTIMAL
1204 #undef SH_ENTRY_HASH
1205 #undef SH_INSERT_HASH_INTERNAL
1206 #undef SH_LOOKUP_HASH_INTERNAL
#define SH_HASH_KEY(tb, key)
#define Assert(condition)
#define SH_GET_HASH(tb, a)
if(TABLE==NULL||TABLE_index==NULL)
void pfree(void *pointer)
void * palloc0(Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
static uint64 pg_nextpower2_64(uint64 num)
static unsigned hash(unsigned *uv, int n)
#define SH_INITIAL_BUCKET
#define SH_UPDATE_PARAMETERS
#define SH_DISTANCE_FROM_OPTIMAL
#define SH_LOOKUP_HASH_INTERNAL
#define SH_INSERT_HASH_INTERNAL
#define SH_START_ITERATE_AT
static pg_noinline void Size size