From ab5b8c6eb4c21dceaf24f2e16405afcc6de5d9b2 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 21 Jan 2021 00:06:58 +0200 Subject: [PATCH v6 3/3] Optimize hash function --- src/backend/utils/resowner/resowner.c | 24 ++++++++++++++++++------ src/include/common/hashfn.h | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index 1db1e7cf14b..72e4d8a784c 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -163,15 +163,27 @@ static void ReleaseAuxProcessResourcesCallback(int code, Datum arg); * INTERNAL ROUTINES * *****************************************************************************/ +/* + * Hash function for value+kind combination. + */ static inline uint32 hash_resource_elem(Datum value, ResourceOwnerFuncs *kind) { - Datum data[2]; - - data[0] = value; - data[1] = PointerGetDatum(kind); - - return hash_bytes((unsigned char *) &data, 2 * SIZEOF_DATUM); + /* + * Most resources types store a pointer in 'value', and pointers are + * unique all on their own. But some resources store plain integers (Files + * and Buffers as of this writing), so we want to incorporate the 'kind' + * in the hash too, otherwise those resources will collide a lot. But + * because there are only a few resource kinds like that - and only a few + * resource kinds to begin with - we don't need to work too hard to mix + * 'kind' into the hash. Just add it with hash_combine(), it perturbs the + * result enough for our purposes. + */ +#if SIZEOF_DATUM == 8 + return hash_combine64(murmurhash64((uint64) value), (uint64) kind); +#else + return hash_combine(murmurhash32((uint32) value), (uint32) kind); +#endif } static void diff --git a/src/include/common/hashfn.h b/src/include/common/hashfn.h index c634cc067a1..009ffbbdd38 100644 --- a/src/include/common/hashfn.h +++ b/src/include/common/hashfn.h @@ -101,4 +101,19 @@ murmurhash32(uint32 data) return h; } +/* 64-bit variant */ +static inline uint64 +murmurhash64(uint64 data) +{ + uint64 h = data; + + h ^= h >> 33; + h *= 0xff51afd7ed558ccd; + h ^= h >> 33; + h *= 0xc4ceb9fe1a85ec53; + h ^= h >> 33; + + return h; +} + #endif /* HASHFN_H */ -- 2.29.2