v5-0004-Add-bytewise-interface-for-incrementing-the-hash-.patch
text/x-patch
Filename: v5-0004-Add-bytewise-interface-for-incrementing-the-hash-.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v5-0004
Subject: Add bytewise interface for incrementing the hash state
| File | + | − |
|---|---|---|
| src/backend/utils/hash/dynahash.c | 3 | 11 |
| src/backend/utils/misc/guc.c | 8 | 8 |
| src/include/common/hashfn_unstable.h | 35 | 0 |
From c2b799dd2418fb68fcfc6ccf006a50f74c9072fe Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Wed, 29 Nov 2023 16:28:58 +0700
Subject: [PATCH v5 4/4] Add bytewise interface for incrementing the hash state
This is the nicest interface for guc_name_hash, and seems
good for string_hash too. It's not clear if this is good for
the latter from a performance perspective.
---
src/backend/utils/hash/dynahash.c | 14 +++--------
src/backend/utils/misc/guc.c | 16 ++++++-------
src/include/common/hashfn_unstable.h | 35 ++++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 1c08dc8942..ab2dbefd12 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -328,19 +328,11 @@ string_hash(const void *key, Size keysize)
fasthash64_init(&hs, 0);
- while (*buf)
+ while (*buf && s_len < keysize)
{
- int chunk_len = 0;
+ s_len++;
- for (int i = 0;
- i < 8 && *buf++ && s_len < keysize;
- i++)
- {
- chunk_len++;
- s_len++;
- }
-
- fasthash64_accum(&hs, buf, chunk_len);
+ fasthash64_accum_byte(&hs, *buf);
}
return fasthash64_final32(&hs);
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 82d8efbc96..2428f2475c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -33,6 +33,7 @@
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_parameter_acl.h"
+#include "common/hashfn_unstable.h"
#include "guc_internal.h"
#include "libpq/pqformat.h"
#include "parser/scansup.h"
@@ -1324,22 +1325,21 @@ guc_name_compare(const char *namea, const char *nameb)
static uint32
guc_name_hash(const void *key, Size keysize)
{
- uint32 result = 0;
const char *name = *(const char *const *) key;
+ fasthash64_state hs;
+
+ fasthash64_init(&hs, 0);
while (*name)
{
char ch = *name++;
- /* Case-fold in the same way as guc_name_compare */
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
+ /* quick and dirty case-folding suitable for hashing */
+ ch |= 0x20;
- /* Merge into hash ... not very bright, but it needn't be */
- result = pg_rotate_left32(result, 5);
- result ^= (uint32) ch;
+ fasthash64_accum_byte(&hs, ch);
}
- return result;
+ return fasthash64_final32(&hs);
}
/*
diff --git a/src/include/common/hashfn_unstable.h b/src/include/common/hashfn_unstable.h
index a95942f7af..1b7db5ac07 100644
--- a/src/include/common/hashfn_unstable.h
+++ b/src/include/common/hashfn_unstable.h
@@ -26,6 +26,7 @@
typedef struct fasthash64_state
{
uint64 accum;
+ int8 accum_len;
uint64 hash;
} fasthash64_state;
@@ -46,6 +47,31 @@ void fasthash64_init(fasthash64_state *hs, uint64_t seed)
// setting seed would go here
}
+static inline
+void fasthash64_accum_byte(fasthash64_state *hs, const unsigned char ch)
+{
+ const uint64_t m = 0x880355f21e6d1965ULL;
+
+ hs->accum |= ch;
+
+ // wip: is there a better way to get sizeof struct member?
+ if (hs->accum_len == sizeof(((fasthash64_state *) 0)->accum))
+ {
+ // combine into hash
+ hs->hash ^= mix(hs->accum);
+ hs->hash *= m;
+
+ // reset accum
+ hs->accum = 0;
+ hs->accum_len = 0;
+ }
+ else
+ {
+ hs->accum <<= sizeof(unsigned char);
+ hs->accum_len += sizeof(unsigned char);
+ }
+}
+
static inline
void fasthash64_accum(fasthash64_state *hs, const void *buf, int len)
{
@@ -94,6 +120,15 @@ void fasthash64_accum(fasthash64_state *hs, const void *buf, int len)
static inline
uint64_t fasthash64_final(fasthash64_state *hs)
{
+ const uint64_t m = 0x880355f21e6d1965ULL;
+
+ // check for remaining bytes to combine into hash
+ if (hs->accum_len > 0)
+ {
+ hs->hash ^= mix(hs->accum);
+ hs->hash *= m;
+ }
+
return mix(hs->hash);
}
--
2.42.0