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_ESTIMATE_SPACE SH_MAKE_NAME(estimate_space)
129#define SH_STAT SH_MAKE_NAME(stat)
132#define SH_COMPUTE_SIZE SH_MAKE_NAME(compute_size)
133#define SH_UPDATE_PARAMETERS SH_MAKE_NAME(update_parameters)
134#define SH_NEXT SH_MAKE_NAME(next)
135#define SH_PREV SH_MAKE_NAME(prev)
136#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
137#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
138#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
139#define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal)
140#define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal)
167#ifndef SH_RAW_ALLOCATOR
190#ifdef SH_RAW_ALLOCATOR
258#ifndef SH_RAW_ALLOCATOR
263#define SH_MAX_SIZE (((uint64) PG_UINT32_MAX) + 1)
267#define SH_FILLFACTOR (0.9)
270#define SH_MAX_FILLFACTOR (0.98)
272#ifndef SH_GROW_MAX_DIB
273#define SH_GROW_MAX_DIB 25
276#ifndef SH_GROW_MAX_MOVE
277#define SH_GROW_MAX_MOVE 150
279#ifndef SH_GROW_MIN_FILLFACTOR
281#define SH_GROW_MIN_FILLFACTOR 0.1
285#define SH_COMPARE_KEYS(tb, ahash, akey, b) (ahash == SH_GET_HASH(tb, b) && SH_EQUAL(tb, b->SH_KEY, akey))
287#define SH_COMPARE_KEYS(tb, ahash, akey, b) (SH_EQUAL(tb, b->SH_KEY, akey))
301#define sh_error(...) pg_fatal(__VA_ARGS__)
302#define sh_log(...) pg_log_info(__VA_ARGS__)
304#define sh_error(...) elog(ERROR, __VA_ARGS__)
305#define sh_log(...) elog(LOG, __VA_ARGS__)
320 size =
Max(newsize, 2);
324 Assert(size <= SH_MAX_SIZE);
331 sh_error(
"hash table too large");
353 if (tb->
size == SH_MAX_SIZE)
370 curelem = (curelem + 1) & tb->
sizemask;
372 Assert(curelem != startelem);
381 curelem = (curelem - 1) & tb->
sizemask;
383 Assert(curelem != startelem);
392 if (optimal <= bucket)
393 return bucket - optimal;
395 return (tb->
size + bucket) - optimal;
412#ifndef SH_USE_NONDEFAULT_ALLOCATOR
418#ifdef SH_RAW_ALLOCATOR
444#ifdef SH_RAW_ALLOCATOR
455#ifdef SH_RAW_ALLOCATOR
464 size =
Min((
double) SH_MAX_SIZE, ((
double) nelements) / SH_FILLFACTOR);
508 Assert(oldsize != SH_MAX_SIZE);
509 Assert(oldsize < newsize);
541 for (
i = 0;
i < oldsize;
i++)
564 copyelem = startelem;
565 for (
i = 0;
i < oldsize;
i++)
578 curelem = startelem2;
583 newentry = &newdata[curelem];
590 curelem =
SH_NEXT(tb, curelem, startelem2);
599 if (copyelem >= oldsize)
634 sh_error(
"hash table size exceeded");
676 if (SH_COMPARE_KEYS(tb,
hash,
key, entry))
687 if (insertdist > curdist)
690 uint32 emptyelem = curelem;
699 emptyelem =
SH_NEXT(tb, emptyelem, startelem);
700 emptyentry = &
data[emptyelem];
704 lastentry = emptyentry;
717 if (
unlikely(++emptydist > SH_GROW_MAX_MOVE) &&
718 ((
double) tb->
members / tb->
size) >= SH_GROW_MIN_FILLFACTOR)
732 moveelem = emptyelem;
733 while (moveelem != curelem)
737 moveelem =
SH_PREV(tb, moveelem, startelem);
738 moveentry = &
data[moveelem];
741 lastentry = moveentry;
756 curelem =
SH_NEXT(tb, curelem, startelem);
767 if (
unlikely(insertdist > SH_GROW_MAX_DIB) &&
768 ((
double) tb->
members / tb->
size) >= SH_GROW_MIN_FILLFACTOR)
807 uint32 curelem = startelem;
820 if (SH_COMPARE_KEYS(tb,
hash,
key, entry))
830 curelem =
SH_NEXT(tb, curelem, startelem);
865 uint32 curelem = startelem;
875 SH_COMPARE_KEYS(tb,
hash,
key, entry))
894 curelem =
SH_NEXT(tb, curelem, startelem);
895 curentry = &tb->
data[curelem];
907 if (curoptimal == curelem)
916 lastentry = curentry;
924 curelem =
SH_NEXT(tb, curelem, startelem);
940 curelem = entry - &tb->
data[0];
957 curelem =
SH_NEXT(tb, curelem, startelem);
958 curentry = &tb->
data[curelem];
970 if (curoptimal == curelem)
979 lastentry = curentry;
1008 Assert(startelem < SH_MAX_SIZE);
1014 iter->
cur = startelem;
1091 nentries = nentries / SH_FILLFACTOR;
1094 if (nentries >= SH_MAX_SIZE)
1098 size = (
uint64) nentries;
1101 size =
Max(size, 2);
1110 if (space >= SIZE_MAX / 2)
1113 return (
size_t) space +
sizeof(
SH_TYPE);
1123 uint32 max_chain_length = 0;
1124 uint32 total_chain_length = 0;
1125 double avg_chain_length;
1130 uint32 total_collisions = 0;
1131 uint32 max_collisions = 0;
1132 double avg_collisions;
1134 for (
i = 0;
i < tb->
size;
i++)
1141 elem = &tb->
data[
i];
1150 if (dist > max_chain_length)
1151 max_chain_length = dist;
1152 total_chain_length += dist;
1154 collisions[optimal]++;
1157 for (
i = 0;
i < tb->
size;
i++)
1159 uint32 curcoll = collisions[
i];
1166 total_collisions += curcoll;
1167 if (curcoll > max_collisions)
1168 max_collisions = curcoll;
1177 avg_chain_length = ((double) total_chain_length) / tb->
members;
1178 avg_collisions = ((double) total_collisions) / tb->
members;
1183 avg_chain_length = 0;
1187 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",
1189 total_collisions, max_collisions, avg_collisions);
1199#undef SH_ELEMENT_TYPE
1206#undef SH_USE_NONDEFAULT_ALLOCATOR
1210#undef SH_MAKE_PREFIX
1214#undef SH_MAX_FILLFACTOR
1215#undef SH_GROW_MAX_DIB
1216#undef SH_GROW_MAX_MOVE
1217#undef SH_GROW_MIN_FILLFACTOR
1223#undef SH_STATUS_EMPTY
1224#undef SH_STATUS_IN_USE
1232#undef SH_INSERT_HASH
1233#undef SH_DELETE_ITEM
1236#undef SH_LOOKUP_HASH
1238#undef SH_START_ITERATE
1239#undef SH_START_ITERATE_AT
1243#undef SH_ESTIMATE_SPACE
1247#undef SH_COMPUTE_SIZE
1248#undef SH_UPDATE_PARAMETERS
1249#undef SH_COMPARE_KEYS
1250#undef SH_INITIAL_BUCKET
1253#undef SH_DISTANCE_FROM_OPTIMAL
1255#undef SH_INSERT_HASH_INTERNAL
1256#undef SH_LOOKUP_HASH_INTERNAL
#define SH_HASH_KEY(tb, key)
#define SH_GET_HASH(tb, a)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void pfree(void *pointer)
void * palloc0(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_ESTIMATE_SPACE
#define SH_DISTANCE_FROM_OPTIMAL
#define SH_LOOKUP_HASH_INTERNAL
#define SH_INSERT_HASH_INTERNAL
#define SH_START_ITERATE_AT