Use a faster hash function in resource owners.
authorHeikki Linnakangas <[email protected]>
Wed, 8 Nov 2023 11:30:52 +0000 (13:30 +0200)
committerHeikki Linnakangas <[email protected]>
Wed, 8 Nov 2023 11:30:52 +0000 (13:30 +0200)
This buys back some of the performance loss that we otherwise saw from the
previous commit.

Reviewed-by: Aleksander Alekseev, Michael Paquier, Julien Rouhaud
Reviewed-by: Kyotaro Horiguchi, Hayato Kuroda, Álvaro Herrera, Zhihong Yu
Reviewed-by: Peter Eisentraut, Andres Freund
Discussion: https://www.postgresql.org/message-id/d746cead-a1ef-7efe-fb47-933311e876a3%40iki.fi

src/backend/utils/resowner/resowner.c
src/include/common/hashfn.h

index 6e4020f241fdd08b0070da4f69ecc346ed4c8c05..eecb3ade3d7c06969f0f5d501881ddc2644dd680 100644 (file)
@@ -206,15 +206,27 @@ static void ReleaseAuxProcessResourcesCallback(int code, Datum arg);
  *       INTERNAL ROUTINES                                                                                                              *
  *****************************************************************************/
 
+/*
+ * Hash function for value+kind combination.
+ */
 static inline uint32
 hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
 {
-       Datum           data[2];
-
-       data[0] = value;
-       data[1] = PointerGetDatum(kind);
-
-       return hash_bytes((unsigned char *) &data, 2 * SIZEOF_DATUM);
+       /*
+        * Most resource kinds 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
 }
 
 /*
index 5e89aef987f1bd8ec43683fa0edeee54873b5275..adc1dc1de89da432d31a43265663809835814c24 100644 (file)
@@ -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 */