diff options
author | Michael Paquier | 2024-03-14 22:57:17 +0000 |
---|---|---|
committer | Michael Paquier | 2024-03-14 22:57:17 +0000 |
commit | cc5ef90edd809eaf85e11a0ee251229bbf7ce798 (patch) | |
tree | ce2a431df14bbcfeaa208e408937854b9fbe640b | |
parent | 4169850f0b6fc98a5f28d2b0ca4c3a4c1ecf4553 (diff) |
Refactor initial hash lookup in dynahash.c
The same pattern is used three times in dynahash.c to retrieve a bucket
number and a hash bucket from a hash value. This has popped up while
discussing improvements for the type cache, where this piece of
refactoring would become useful.
Note that hash_search_with_hash_value() does not need the bucket number,
just the hash bucket.
Author: Teodor Sigaev
Reviewed-by: Aleksander Alekseev, Michael Paquier
Discussion: https://postgr.es/m/5812a6e5-68ae-4d84-9d85-b443176966a1@sigaev.ru
-rw-r--r-- | src/backend/utils/hash/dynahash.c | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index a4152080b5d..4080833df0f 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -273,6 +273,8 @@ static void hdefault(HTAB *hashp); static int choose_nelem_alloc(Size entrysize); static bool init_htab(HTAB *hashp, long nelem); static void hash_corrupted(HTAB *hashp); +static uint32 hash_initial_lookup(HTAB *hashp, uint32 hashvalue, + HASHBUCKET **bucketptr); static long next_pow2_long(long num); static int next_pow2_int(long num); static void register_seq_scan(HTAB *hashp); @@ -972,10 +974,6 @@ hash_search_with_hash_value(HTAB *hashp, HASHHDR *hctl = hashp->hctl; int freelist_idx = FREELIST_IDX(hctl, hashvalue); Size keysize; - uint32 bucket; - long segment_num; - long segment_ndx; - HASHSEGMENT segp; HASHBUCKET currBucket; HASHBUCKET *prevBucketPtr; HashCompareFunc match; @@ -1008,17 +1006,7 @@ hash_search_with_hash_value(HTAB *hashp, /* * Do the initial lookup */ - bucket = calc_bucket(hctl, hashvalue); - - segment_num = bucket >> hashp->sshift; - segment_ndx = MOD(bucket, hashp->ssize); - - segp = hashp->dir[segment_num]; - - if (segp == NULL) - hash_corrupted(hashp); - - prevBucketPtr = &segp[segment_ndx]; + (void) hash_initial_lookup(hashp, hashvalue, &prevBucketPtr); currBucket = *prevBucketPtr; /* @@ -1159,14 +1147,10 @@ hash_update_hash_key(HTAB *hashp, const void *newKeyPtr) { HASHELEMENT *existingElement = ELEMENT_FROM_KEY(existingEntry); - HASHHDR *hctl = hashp->hctl; uint32 newhashvalue; Size keysize; uint32 bucket; uint32 newbucket; - long segment_num; - long segment_ndx; - HASHSEGMENT segp; HASHBUCKET currBucket; HASHBUCKET *prevBucketPtr; HASHBUCKET *oldPrevPtr; @@ -1187,17 +1171,8 @@ hash_update_hash_key(HTAB *hashp, * this to be able to unlink it from its hash chain, but as a side benefit * we can verify the validity of the passed existingEntry pointer. */ - bucket = calc_bucket(hctl, existingElement->hashvalue); - - segment_num = bucket >> hashp->sshift; - segment_ndx = MOD(bucket, hashp->ssize); - - segp = hashp->dir[segment_num]; - - if (segp == NULL) - hash_corrupted(hashp); - - prevBucketPtr = &segp[segment_ndx]; + bucket = hash_initial_lookup(hashp, existingElement->hashvalue, + &prevBucketPtr); currBucket = *prevBucketPtr; while (currBucket != NULL) @@ -1219,18 +1194,7 @@ hash_update_hash_key(HTAB *hashp, * chain we want to put the entry into. */ newhashvalue = hashp->hash(newKeyPtr, hashp->keysize); - - newbucket = calc_bucket(hctl, newhashvalue); - - segment_num = newbucket >> hashp->sshift; - segment_ndx = MOD(newbucket, hashp->ssize); - - segp = hashp->dir[segment_num]; - - if (segp == NULL) - hash_corrupted(hashp); - - prevBucketPtr = &segp[segment_ndx]; + newbucket = hash_initial_lookup(hashp, newhashvalue, &prevBucketPtr); currBucket = *prevBucketPtr; /* @@ -1741,6 +1705,33 @@ element_alloc(HTAB *hashp, int nelem, int freelist_idx) return true; } +/* + * Do initial lookup of a bucket for the given hash value, retrieving its + * bucket number and its hash bucket. + */ +static inline uint32 +hash_initial_lookup(HTAB *hashp, uint32 hashvalue, HASHBUCKET **bucketptr) +{ + HASHHDR *hctl = hashp->hctl; + HASHSEGMENT segp; + long segment_num; + long segment_ndx; + uint32 bucket; + + bucket = calc_bucket(hctl, hashvalue); + + segment_num = bucket >> hashp->sshift; + segment_ndx = MOD(bucket, hashp->ssize); + + segp = hashp->dir[segment_num]; + + if (segp == NULL) + hash_corrupted(hashp); + + *bucketptr = &segp[segment_ndx]; + return bucket; +} + /* complain when we have detected a corrupted hashtable */ static void hash_corrupted(HTAB *hashp) |