From 16875c7c32a7e20cddf1e18c918be418f8a88046 Mon Sep 17 00:00:00 2001
From: David Rowley <dgrowley@gmail.com>
Date: Mon, 18 Aug 2025 12:32:02 +1200
Subject: [PATCH v2 1/2] Use elog(DEBUG4) for dynahash.c statistics output

Previously this was being output to stderr.  This commit adjusts things
to use elog(DEBUG4).  Here we also adjust the format of the message to
add the hash table name and also put it on a single line.  This should
make grepping the logs for this information easier.

Also get rid of the global hash table statistics.  This seems very dated
and didn't fit very well with trying to put all the statistics for a
specific hash table on a single log line.

The main aim here is to allow it so we can have at least one buildfarm
member build with HASH_STATISTICS to prevent future changes from breaking
things in that area.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAApHDvoccvJ9CG5zx+i-EyCzJbcL5K=CzqrnL_YN59qaL5hiaw@mail.gmail.com
---
 src/backend/utils/hash/dynahash.c | 40 +++++++++++--------------------
 src/include/utils/hsearch.h       |  2 +-
 2 files changed, 15 insertions(+), 27 deletions(-)

diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index d0843551007..2b22c65e541 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -205,8 +205,9 @@ struct HASHHDR
 	 * Count statistics here.  NB: stats code doesn't bother with mutex, so
 	 * counts could be corrupted a bit in a partitioned table.
 	 */
-	long		accesses;
-	long		collisions;
+	uint64		accesses;
+	uint64		collisions;
+	uint64		expansions;
 #endif
 };
 
@@ -266,12 +267,6 @@ struct HTAB
  */
 #define MOD(x,y)			   ((x) & ((y)-1))
 
-#ifdef HASH_STATISTICS
-static long hash_accesses,
-			hash_collisions,
-			hash_expansions;
-#endif
-
 /*
  * Private function prototypes
  */
@@ -661,7 +656,7 @@ hdefault(HTAB *hashp)
 	hctl->isfixed = false;		/* can be enlarged */
 
 #ifdef HASH_STATISTICS
-	hctl->accesses = hctl->collisions = 0;
+	hctl->accesses = hctl->collisions = hctl->expansions = 0;
 #endif
 }
 
@@ -888,7 +883,7 @@ hash_destroy(HTAB *hashp)
 		/* so this hashtable must have its own context */
 		Assert(hashp->hcxt != NULL);
 
-		hash_stats("destroy", hashp);
+		hash_stats(__func__, hashp);
 
 		/*
 		 * Free everything by destroying the hash table's memory context.
@@ -898,19 +893,16 @@ hash_destroy(HTAB *hashp)
 }
 
 void
-hash_stats(const char *where, HTAB *hashp)
+hash_stats(const char *caller, HTAB *hashp)
 {
 #ifdef HASH_STATISTICS
-	fprintf(stderr, "%s: this HTAB -- accesses %ld collisions %ld\n",
-			where, hashp->hctl->accesses, hashp->hctl->collisions);
-
-	fprintf(stderr, "hash_stats: entries %ld keysize %ld maxp %u segmentcount %ld\n",
-			hash_get_num_entries(hashp), (long) hashp->hctl->keysize,
-			hashp->hctl->max_bucket, hashp->hctl->nsegs);
-	fprintf(stderr, "%s: total accesses %ld total collisions %ld\n",
-			where, hash_accesses, hash_collisions);
-	fprintf(stderr, "hash_stats: total expansions %ld\n",
-			hash_expansions);
+	HASHHDR    *hctl = hashp->hctl;
+
+	elog(DEBUG4,
+		 "hash_stats:  Caller: %s  Table Name: \"%s\"  Accesses: " UINT64_FORMAT "  Collisions: " UINT64_FORMAT "  Expansions: " UINT64_FORMAT "  Entries: %ld  Key Size: %zu  Max Bucket: %u  Segment Count: %ld",
+		 caller != NULL ? caller : "(unknown)", hashp->tabname, hctl->accesses,
+		 hctl->collisions, hctl->expansions, hash_get_num_entries(hashp),
+		 hctl->keysize, hctl->max_bucket, hctl->nsegs);
 #endif
 }
 
@@ -996,7 +988,6 @@ hash_search_with_hash_value(HTAB *hashp,
 	HashCompareFunc match;
 
 #ifdef HASH_STATISTICS
-	hash_accesses++;
 	hctl->accesses++;
 #endif
 
@@ -1040,7 +1031,6 @@ hash_search_with_hash_value(HTAB *hashp,
 		prevBucketPtr = &(currBucket->link);
 		currBucket = *prevBucketPtr;
 #ifdef HASH_STATISTICS
-		hash_collisions++;
 		hctl->collisions++;
 #endif
 	}
@@ -1176,7 +1166,6 @@ hash_update_hash_key(HTAB *hashp,
 #ifdef HASH_STATISTICS
 	HASHHDR    *hctl = hashp->hctl;
 
-	hash_accesses++;
 	hctl->accesses++;
 #endif
 
@@ -1230,7 +1219,6 @@ hash_update_hash_key(HTAB *hashp,
 		prevBucketPtr = &(currBucket->link);
 		currBucket = *prevBucketPtr;
 #ifdef HASH_STATISTICS
-		hash_collisions++;
 		hctl->collisions++;
 #endif
 	}
@@ -1586,7 +1574,7 @@ expand_table(HTAB *hashp)
 	Assert(!IS_PARTITIONED(hctl));
 
 #ifdef HASH_STATISTICS
-	hash_expansions++;
+	hctl->expansions++;
 #endif
 
 	new_bucket = hctl->max_bucket + 1;
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index 932cc4f34d9..80deb8e543e 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -132,7 +132,7 @@ typedef struct
 extern HTAB *hash_create(const char *tabname, long nelem,
 						 const HASHCTL *info, int flags);
 extern void hash_destroy(HTAB *hashp);
-extern void hash_stats(const char *where, HTAB *hashp);
+extern void hash_stats(const char *caller, HTAB *hashp);
 extern void *hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action,
 						 bool *foundPtr);
 extern uint32 get_hash_value(HTAB *hashp, const void *keyPtr);
-- 
2.43.0

