v7-0003-Combine-firstTuple-and-additionalsize-into-a-sing.patch

text/x-patch

Filename: v7-0003-Combine-firstTuple-and-additionalsize-into-a-sing.patch
Type: text/x-patch
Part: 2
Message: Re: Reduce TupleHashEntryData struct size by half

Patch

Format: format-patch
Series: patch v7-0003
Subject: Combine firstTuple and additionalsize into a single allocation.
File+
src/backend/executor/execGrouping.c 26 7
src/include/executor/executor.h 5 4
src/include/nodes/execnodes.h 0 1
From 3e21d4328af39e52df0e1ec49a8234a328506f75 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Tue, 14 Jan 2025 16:17:00 -0800
Subject: [PATCH v7 3/4] Combine firstTuple and additionalsize into a single
 allocation.

Saves space in TupleHashEntryData by removing the "additional"
pointer. TupleHashEntryData is required for each bucket, whether
occupied or not, so that space is more valuable than other hash table
allocations.

Discussion: https://postgr.es/m/817d244237878cebdff0bc363718feaf49a1ea7d.camel%40j-davis.com
---
 src/backend/executor/execGrouping.c | 33 +++++++++++++++++++++++------
 src/include/executor/executor.h     |  9 ++++----
 src/include/nodes/execnodes.h       |  1 -
 3 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 450fe74bec5..76b16101dbd 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -196,7 +196,7 @@ BuildTupleHashTable(PlanState *parent,
 	hashtable->tab_collations = collations;
 	hashtable->tablecxt = tablecxt;
 	hashtable->tempcxt = tempcxt;
-	hashtable->additionalsize = additionalsize;
+	hashtable->additionalsize = MAXALIGN(additionalsize);
 	hashtable->tableslot = NULL;	/* will be made on first lookup */
 	hashtable->inputslot = NULL;
 	hashtable->in_hash_expr = NULL;
@@ -478,15 +478,34 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
 		}
 		else
 		{
+			char	   *data;
+			MinimalTuple tmpTuple;
+			Size		totalsize;
+
 			/* created new entry */
 			*isnew = true;
 
-			MemoryContextSwitchTo(hashtable->tablecxt);
-
-			/* Copy the first tuple into the table context */
-			entry->firstTuple = ExecCopySlotMinimalTuple(slot);
-
-			entry->additional = palloc0(hashtable->additionalsize);
+			/* get minimal tuple in temp context */
+			MemoryContextSwitchTo(hashtable->tempcxt);
+			tmpTuple = ExecCopySlotMinimalTuple(slot);
+
+			/*
+			 * Allocate space for additionalsize followed by the MinimalTuple
+			 * in the table context, and copy the tuple. A single allocation
+			 * avoids the need to store two pointers in TupleHashEntryData.
+			 */
+			totalsize = hashtable->additionalsize + tmpTuple->t_len;
+			data = MemoryContextAlloc(hashtable->tablecxt, totalsize);
+			memset(data, 0, hashtable->additionalsize);
+
+			/*
+			 * firstTuple points in the middle of the allocated space. The
+			 * additional data pointer can be computed by subtracting
+			 * additionalsize from firstTuple.
+			 */
+			data += hashtable->additionalsize;
+			entry->firstTuple = (MinimalTuple) data;
+			memcpy(entry->firstTuple, tmpTuple, tmpTuple->t_len);
 		}
 	}
 	else
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index ee93b479c92..344c5f8a54b 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -178,15 +178,16 @@ TupleHashEntryGetTuple(TupleHashEntry entry)
 
 /*
  * Get a pointer into the additional space allocated for this entry. The
- * amount of space available is the additionalsize specified to
- * BuildTupleHashTable(). If additionalsize was specified as zero, no
+ * memory will be maxaligned and zeroed.
+ *
+ * The amount of space available is the additionalsize requested in the call
+ * to BuildTupleHashTable(). If additionalsize was specified as zero, no
  * additional space is available and this function should not be called.
  */
 static inline void *
 TupleHashEntryGetAdditional(TupleHashTable hashtable, TupleHashEntry entry)
 {
-	Assert(entry->additional != NULL);
-	return entry->additional;
+	return (char *) entry->firstTuple - hashtable->additionalsize;
 }
 #endif
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 11aa110cf9c..a875335cb09 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -837,7 +837,6 @@ typedef struct TupleHashTableData *TupleHashTable;
 typedef struct TupleHashEntryData
 {
 	MinimalTuple firstTuple;	/* copy of first tuple in this group */
-	void	   *additional;		/* user data */
 	uint32		status;			/* hash status */
 	uint32		hash;			/* hash value (cached) */
 } TupleHashEntryData;
-- 
2.34.1