Simplify initialization of incremental hash state
authorJohn Naylor <john.naylor@postgresql.org>
Sun, 21 Jan 2024 12:19:14 +0000 (19:19 +0700)
committerJohn Naylor <john.naylor@postgresql.org>
Tue, 6 Feb 2024 07:39:36 +0000 (14:39 +0700)
The standalone functions fasthash{32,64} use length for two purposes:
how many bytes to hash, and how to perturb the internal seed.

Developers using the incremental interface may not know the length
ahead of time (e.g. for C strings). In this case, it's advised to
pass length to the finalizer, but initialization still needed some
length up front, in the form of a placeholder macro.

Separate the concerns by having the standalone functions perturb the
internal seed themselves from their own length parameter, allowing
to remove "len" from fasthash_init(), as well as the placeholder macro.

Discussion: https://postgr.es/m/CANWCAZbTUk2LOyhsFo33gjLyLAHZ7ucXCi5K9u%3D%2BPtnTShDKtw%40mail.gmail.com

src/backend/catalog/namespace.c
src/include/common/hashfn_unstable.h

index b610aa62423d36c4b10017d0ea996ed7a6fced06..8df30b244013904ff0ef8146973c12529513e149 100644 (file)
@@ -256,7 +256,7 @@ spcachekey_hash(SearchPathCacheKey key)
    fasthash_state hs;
    int         sp_len;
 
-   fasthash_init(&hs, FH_UNKNOWN_LENGTH, 0);
+   fasthash_init(&hs, 0);
 
    hs.accum = key.roleid;
    fasthash_combine(&hs);
index 3d927e1fb18ace6bc5317bd7db2ab18389232ff9..63ebe295c5f5f49854730e28bb11b909c1bc80b2 100644 (file)
  * in fasthash_accum_cstring() :
  *
  * fasthash_state hs;
- * fasthash_init(&hs, FH_UNKNOWN_LENGTH, 0);
+ * fasthash_init(&hs, 0);
  * len = fasthash_accum_cstring(&hs, *str);
  * ...
  * return fasthash_final32(&hs, len);
  *
- * Here we pass FH_UNKNOWN_LENGTH as a convention, since passing zero
- * would zero out the internal seed as well. fasthash_accum_cstring()
- * returns the length of the string, which is computed on-the-fly while
- * mixing the string into the hash. Experimentation has found that
+ * The length is computed on-the-fly. Experimentation has found that
  * SMHasher fails unless we incorporate the length, so it is passed to
  * the finalizer as a tweak.
  */
@@ -89,20 +86,17 @@ typedef struct fasthash_state
 
 #define FH_SIZEOF_ACCUM sizeof(uint64)
 
-#define FH_UNKNOWN_LENGTH 1
 
 /*
  * Initialize the hash state.
  *
- * 'len' is the length of the input, if known ahead of time.
- * If that is not known, pass FH_UNKNOWN_LENGTH.
  * 'seed' can be zero.
  */
 static inline void
-fasthash_init(fasthash_state *hs, int len, uint64 seed)
+fasthash_init(fasthash_state *hs, uint64 seed)
 {
    memset(hs, 0, sizeof(fasthash_state));
-   hs->hash = seed ^ (len * 0x880355f21e6d1965);
+   hs->hash = seed ^ 0x880355f21e6d1965;
 }
 
 /* both the finalizer and part of the combining step */
@@ -328,7 +322,10 @@ fasthash64(const char *k, int len, uint64 seed)
 {
    fasthash_state hs;
 
-   fasthash_init(&hs, len, seed);
+   fasthash_init(&hs, 0);
+
+   /* re-initialize the seed according to input length */
+   hs.hash = seed ^ (len * 0x880355f21e6d1965);
 
    while (len >= FH_SIZEOF_ACCUM)
    {