v10jd-0004-Optimize-hash-function-further.patch
text/x-patch
Filename: v10jd-0004-Optimize-hash-function-further.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 0004
Subject: Optimize hash function further.
| File | + | − |
|---|---|---|
| src/backend/catalog/namespace.c | 42 | 4 |
| src/include/common/hashfn_unstable.h | 9 | 0 |
From 055d5cc24404584fd98109fabdcf83348e5c49b4 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Mon, 18 Dec 2023 16:44:27 -0800
Subject: [PATCH v10jd] Optimize hash function further.
---
src/backend/catalog/namespace.c | 46 +++++++++++++++++++++++++---
src/include/common/hashfn_unstable.h | 9 ++++++
2 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index c23f46aca3..368a7fabec 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -245,15 +245,44 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
* offers a more convenient API.
*/
+/* From: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord */
+#define haszero64(v) \
+ (((v) - 0x0101010101010101UL) & ~(v) & 0x8080808080808080UL)
+
static inline uint32
-spcachekey_hash(SearchPathCacheKey key)
+cstring_hash_aligned(const char *str, uint64 seed)
+{
+ const char *const start = str;
+ const char *buf = start;
+ int chunk_len = 0;
+ fasthash_state hs;
+
+ fasthash_init(&hs, FH_UNKNOWN_LENGTH, seed);
+
+ Assert(PointerIsAligned(start, uint64));
+ while (!haszero64(*(uint64 *)buf))
+ {
+ fasthash_accum64(&hs, buf);
+ buf += sizeof(uint64);
+ }
+
+ while (buf[chunk_len] != '\0')
+ chunk_len++;
+ fasthash_accum(&hs, buf, chunk_len);
+ buf += chunk_len;
+
+ return fasthash_final32(&hs, buf - start);
+}
+
+static inline uint32
+cstring_hash_unaligned(const char *str, uint64 seed)
{
- const char *const start = key.searchPath;
- const char *buf = key.searchPath;
+ const char *const start = str;
+ const char *buf = str;
fasthash_state hs;
/* WIP: maybe roleid should be mixed in normally */
- fasthash_init(&hs, FH_UNKNOWN_LENGTH, key.roleid);
+ fasthash_init(&hs, FH_UNKNOWN_LENGTH, seed);
while (*buf)
{
int chunk_len = 0;
@@ -269,6 +298,15 @@ spcachekey_hash(SearchPathCacheKey key)
return fasthash_final32(&hs, buf - start);
}
+static inline uint32
+spcachekey_hash(SearchPathCacheKey key)
+{
+ if (PointerIsAligned(key.searchPath, uint64))
+ return cstring_hash_aligned(key.searchPath, key.roleid);
+ else
+ return cstring_hash_unaligned(key.searchPath, key.roleid);
+}
+
static inline bool
spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
{
diff --git a/src/include/common/hashfn_unstable.h b/src/include/common/hashfn_unstable.h
index bf1dbee28d..553fab0415 100644
--- a/src/include/common/hashfn_unstable.h
+++ b/src/include/common/hashfn_unstable.h
@@ -105,6 +105,15 @@ fasthash_combine(fasthash_state *hs)
hs->accum = 0;
}
+/* Accumulate 8 bytes from aligned pointer and combine it into the hash */
+static inline void
+fasthash_accum64(fasthash_state *hs, const char *ptr)
+{
+ Assert(PointerIsAligned(ptr, uint64));
+ hs->accum = *(uint64 *)ptr;
+ fasthash_combine(hs);
+}
+
/* Accumulate up to 8 bytes of input and combine it into the hash */
static inline void
fasthash_accum(fasthash_state *hs, const char *k, int len)
--
2.34.1