v2-0002-Remove-HASH_SEGMENT-option.patch
text/x-patch
Filename: v2-0002-Remove-HASH_SEGMENT-option.patch
Type: text/x-patch
Part: 1
Message:
Re: Shared hash table allocations
Patch
Format: format-patch
Series: patch v2-0002
Subject: Remove HASH_SEGMENT option
| File | + | − |
|---|---|---|
| src/backend/utils/hash/dynahash.c | 22 | 43 |
| src/include/utils/hsearch.h | 1 | 3 |
From 6b2a6d9e7f718cfc0db43d88815ce2852b7f4957 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 30 Mar 2026 18:20:56 +0300
Subject: [PATCH v2 2/8] Remove HASH_SEGMENT option
It's been unused forever. There's no urgency in removing it now, but
it was just something that caught my eye.
Aleksander Alekseev proposed this a long time ago [0], but Tom Lane
was worried about third-party extensions using it. I believe that to
not be an issue; I tried grepping through all extensions found on
github and didn't find any references to it.
[0] https://www.postgresql.org/message-id/20160418180711.55ac82c0@fujitsu
Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://www.postgresql.org/message-id/01ab1d41-3eda-4705-8bbd-af898f5007f1@iki.fi
---
src/backend/utils/hash/dynahash.c | 65 +++++++++++--------------------
src/include/utils/hsearch.h | 4 +-
2 files changed, 23 insertions(+), 46 deletions(-)
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 11f5778eba1..af3f7142afb 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -108,11 +108,11 @@
/*
* Constants
*
- * A hash table has a top-level "directory", each of whose entries points
- * to a "segment" of ssize bucket headers. The maximum number of hash
- * buckets is thus dsize * ssize (but dsize may be expansible). Of course,
- * the number of records in the table can be larger, but we don't want a
- * whole lot of records per bucket or performance goes down.
+ * A hash table has a top-level "directory", each of whose entries points to a
+ * "segment" of HASH_SEGSIZE bucket headers. The maximum number of hash
+ * buckets is thus dsize * HASH_SEGSIZE (but dsize may be expansible). Of
+ * course, the number of records in the table can be larger, but we don't want
+ * a whole lot of records per bucket or performance goes down.
*
* In a hash table allocated in shared memory, the directory cannot be
* expanded because it must stay at a fixed address. The directory size
@@ -120,8 +120,8 @@
* a good idea of the maximum number of entries!). For non-shared hash
* tables, the initial directory size can be left at the default.
*/
-#define DEF_SEGSIZE 256
-#define DEF_SEGSIZE_SHIFT 8 /* must be log2(DEF_SEGSIZE) */
+#define HASH_SEGSIZE 256
+#define HASH_SEGSIZE_SHIFT 8 /* must be log2(HASH_SEGSIZE) */
#define DEF_DIRSIZE 256
/* Number of freelists to be used for a partitioned hash table. */
@@ -192,8 +192,6 @@ struct HASHHDR
Size entrysize; /* total user element size in bytes */
int64 num_partitions; /* # partitions (must be power of 2), or 0 */
int64 max_dsize; /* 'dsize' limit if directory is fixed size */
- int64 ssize; /* segment size --- must be power of 2 */
- int sshift; /* segment shift = log2(ssize) */
int nelem_alloc; /* number of entries to allocate at once */
bool isfixed; /* if true, don't enlarge */
@@ -235,8 +233,6 @@ struct HTAB
/* We keep local copies of these fixed values to reduce contention */
Size keysize; /* hash key length in bytes */
- int64 ssize; /* segment size --- must be power of 2 */
- int sshift; /* segment shift = log2(ssize) */
/*
* In a USE_VALGRIND build, non-shared hashtables keep an slist chain of
@@ -499,8 +495,6 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
/* make local copies of some heavily-used values */
hctl = hashp->hctl;
hashp->keysize = hctl->keysize;
- hashp->ssize = hctl->ssize;
- hashp->sshift = hctl->sshift;
return hashp;
}
@@ -544,14 +538,6 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
hctl->num_partitions = info->num_partitions;
}
- if (flags & HASH_SEGMENT)
- {
- hctl->ssize = info->ssize;
- hctl->sshift = my_log2(info->ssize);
- /* ssize had better be a power of 2 */
- Assert(hctl->ssize == (1L << hctl->sshift));
- }
-
/*
* SHM hash tables have fixed directory size passed by the caller.
*/
@@ -567,8 +553,6 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
/* make local copies of heavily-used constant fields */
hashp->keysize = hctl->keysize;
- hashp->ssize = hctl->ssize;
- hashp->sshift = hctl->sshift;
/* Build the hash directory structure */
if (!init_htab(hashp, nelem))
@@ -649,9 +633,6 @@ hdefault(HTAB *hashp)
/* table has no fixed maximum size */
hctl->max_dsize = NO_MAX_DSIZE;
- hctl->ssize = DEF_SEGSIZE;
- hctl->sshift = DEF_SEGSIZE_SHIFT;
-
hctl->isfixed = false; /* can be enlarged */
#ifdef HASH_STATISTICS
@@ -733,7 +714,7 @@ init_htab(HTAB *hashp, int64 nelem)
/*
* Figure number of directory segments needed, round up to a power of 2
*/
- nsegs = (nbuckets - 1) / hctl->ssize + 1;
+ nsegs = (nbuckets - 1) / HASH_SEGSIZE + 1;
nsegs = next_pow2_int(nsegs);
/*
@@ -793,7 +774,7 @@ hash_estimate_size(int64 num_entries, Size entrysize)
/* estimate number of buckets wanted */
nBuckets = next_pow2_int64(num_entries);
/* # of segments needed for nBuckets */
- nSegments = next_pow2_int64((nBuckets - 1) / DEF_SEGSIZE + 1);
+ nSegments = next_pow2_int64((nBuckets - 1) / HASH_SEGSIZE + 1);
/* directory entries */
nDirEntries = DEF_DIRSIZE;
while (nDirEntries < nSegments)
@@ -805,7 +786,7 @@ hash_estimate_size(int64 num_entries, Size entrysize)
size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT)));
/* segments */
size = add_size(size, mul_size(nSegments,
- MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET))));
+ MAXALIGN(HASH_SEGSIZE * sizeof(HASHBUCKET))));
/* elements --- allocated in groups of choose_nelem_alloc() entries */
elementAllocCnt = choose_nelem_alloc(entrysize);
nElementAllocs = (num_entries - 1) / elementAllocCnt + 1;
@@ -836,7 +817,7 @@ hash_select_dirsize(int64 num_entries)
/* estimate number of buckets wanted */
nBuckets = next_pow2_int64(num_entries);
/* # of segments needed for nBuckets */
- nSegments = next_pow2_int64((nBuckets - 1) / DEF_SEGSIZE + 1);
+ nSegments = next_pow2_int64((nBuckets - 1) / HASH_SEGSIZE + 1);
/* directory entries */
nDirEntries = DEF_DIRSIZE;
while (nDirEntries < nSegments)
@@ -1417,7 +1398,6 @@ hash_seq_search(HASH_SEQ_STATUS *status)
HTAB *hashp;
HASHHDR *hctl;
uint32 max_bucket;
- int64 ssize;
int64 segment_num;
int64 segment_ndx;
HASHSEGMENT segp;
@@ -1457,7 +1437,6 @@ hash_seq_search(HASH_SEQ_STATUS *status)
curBucket = status->curBucket;
hashp = status->hashp;
hctl = hashp->hctl;
- ssize = hashp->ssize;
max_bucket = hctl->max_bucket;
if (curBucket > max_bucket)
@@ -1469,8 +1448,8 @@ hash_seq_search(HASH_SEQ_STATUS *status)
/*
* first find the right segment in the table directory.
*/
- segment_num = curBucket >> hashp->sshift;
- segment_ndx = MOD(curBucket, ssize);
+ segment_num = curBucket >> HASH_SEGSIZE_SHIFT;
+ segment_ndx = MOD(curBucket, HASH_SEGSIZE);
segp = hashp->dir[segment_num];
@@ -1489,7 +1468,7 @@ hash_seq_search(HASH_SEQ_STATUS *status)
hash_seq_term(status);
return NULL; /* search is done */
}
- if (++segment_ndx >= ssize)
+ if (++segment_ndx >= HASH_SEGSIZE)
{
segment_num++;
segment_ndx = 0;
@@ -1566,8 +1545,8 @@ expand_table(HTAB *hashp)
#endif
new_bucket = hctl->max_bucket + 1;
- new_segnum = new_bucket >> hashp->sshift;
- new_segndx = MOD(new_bucket, hashp->ssize);
+ new_segnum = new_bucket >> HASH_SEGSIZE_SHIFT;
+ new_segndx = MOD(new_bucket, HASH_SEGSIZE);
if (new_segnum >= hctl->nsegs)
{
@@ -1606,8 +1585,8 @@ expand_table(HTAB *hashp)
* split at this point. With a different way of reducing the hash value,
* that might not be true!
*/
- old_segnum = old_bucket >> hashp->sshift;
- old_segndx = MOD(old_bucket, hashp->ssize);
+ old_segnum = old_bucket >> HASH_SEGSIZE_SHIFT;
+ old_segndx = MOD(old_bucket, HASH_SEGSIZE);
old_seg = hashp->dir[old_segnum];
new_seg = hashp->dir[new_segnum];
@@ -1684,12 +1663,12 @@ seg_alloc(HTAB *hashp)
HASHSEGMENT segp;
CurrentDynaHashCxt = hashp->hcxt;
- segp = (HASHSEGMENT) hashp->alloc(sizeof(HASHBUCKET) * hashp->ssize);
+ segp = (HASHSEGMENT) hashp->alloc(sizeof(HASHBUCKET) * HASH_SEGSIZE);
if (!segp)
return NULL;
- MemSet(segp, 0, sizeof(HASHBUCKET) * hashp->ssize);
+ MemSet(segp, 0, sizeof(HASHBUCKET) * HASH_SEGSIZE);
return segp;
}
@@ -1786,8 +1765,8 @@ hash_initial_lookup(HTAB *hashp, uint32 hashvalue, HASHBUCKET **bucketptr)
bucket = calc_bucket(hctl, hashvalue);
- segment_num = bucket >> hashp->sshift;
- segment_ndx = MOD(bucket, hashp->ssize);
+ segment_num = bucket >> HASH_SEGSIZE_SHIFT;
+ segment_ndx = MOD(bucket, HASH_SEGSIZE);
segp = hashp->dir[segment_num];
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index cdc530fb732..0721849c036 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -66,8 +66,6 @@ typedef struct HASHCTL
{
/* Used if HASH_PARTITION flag is set: */
int64 num_partitions; /* # partitions (must be power of 2) */
- /* Used if HASH_SEGMENT flag is set: */
- int64 ssize; /* segment size */
/* Used if HASH_DIRSIZE flag is set: */
int64 dsize; /* (initial) directory size */
int64 max_dsize; /* limit to dsize if dir size is limited */
@@ -90,7 +88,7 @@ typedef struct HASHCTL
/* Flag bits for hash_create; most indicate which parameters are supplied */
#define HASH_PARTITION 0x0001 /* Hashtable is used w/partitioned locking */
-#define HASH_SEGMENT 0x0002 /* Set segment size */
+/* 0x0002 is unused */
#define HASH_DIRSIZE 0x0004 /* Set directory size (initial and max) */
#define HASH_ELEM 0x0008 /* Set keysize and entrysize (now required!) */
#define HASH_STRINGS 0x0010 /* Select support functions for string keys */
--
2.47.3