From b089c9ceabc68d1937cab3185fdfb50f8039c69b Mon Sep 17 00:00:00 2001
From: David Rowley <dgrowley@gmail.com>
Date: Tue, 6 Jul 2021 00:31:57 +1200
Subject: [PATCH v3 2/4] Reduce the number of pallocs in create_hash_bounds

Make the hbounds array an array of PartitionHashBound rather than array of
PartitionHashBound pointers with individually allocated elements.

Also, make the resulting PartitionBoundInfo's datum array elements point
to elements of a single allocation rather than allocating an array of 2
Datum pointers for each partition.

Author: Justin Pryzby
Reviewed-by: Nitin Jadhav
Discussion: https://postgr.es/m/flat/CAMm1aWYFTqEio3bURzZh47jveiHRwgQTiSDvBORczNEz2duZ1Q@mail.gmail.com
---
 src/backend/partitioning/partbounds.c | 39 +++++++++++++--------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 12ad45fedf..e809fb9dda 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -358,10 +358,10 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 				   PartitionKey key, int **mapping)
 {
 	PartitionBoundInfo boundinfo;
-	PartitionHashBound **hbounds = NULL;
+	PartitionHashBound *hbounds;
 	int			i;
-	int			ndatums = 0;
 	int			greatest_modulus;
+	Datum	   *boundDatums;
 
 	boundinfo = (PartitionBoundInfoData *)
 		palloc0(sizeof(PartitionBoundInfoData));
@@ -370,9 +370,8 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->null_index = -1;
 	boundinfo->default_index = -1;
 
-	ndatums = nparts;
-	hbounds = (PartitionHashBound **)
-		palloc(nparts * sizeof(PartitionHashBound *));
+	hbounds = (PartitionHashBound *)
+		palloc(nparts * sizeof(PartitionHashBound));
 
 	/* Convert from node to the internal representation */
 	for (i = 0; i < nparts; i++)
@@ -382,26 +381,27 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 		if (spec->strategy != PARTITION_STRATEGY_HASH)
 			elog(ERROR, "invalid strategy in partition bound spec");
 
-		hbounds[i] = (PartitionHashBound *) palloc(sizeof(PartitionHashBound));
-		hbounds[i]->modulus = spec->modulus;
-		hbounds[i]->remainder = spec->remainder;
-		hbounds[i]->index = i;
+		hbounds[i].modulus = spec->modulus;
+		hbounds[i].remainder = spec->remainder;
+		hbounds[i].index = i;
 	}
 
 	/* Sort all the bounds in ascending order */
-	qsort(hbounds, nparts, sizeof(PartitionHashBound *),
+	qsort(hbounds, nparts, sizeof(PartitionHashBound),
 		  qsort_partition_hbound_cmp);
 
 	/* After sorting, moduli are now stored in ascending order. */
-	greatest_modulus = hbounds[ndatums - 1]->modulus;
+	greatest_modulus = hbounds[nparts - 1].modulus;
 
-	boundinfo->ndatums = ndatums;
-	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+	boundinfo->ndatums = nparts;
+	boundinfo->datums = (Datum **) palloc0(nparts * sizeof(Datum *));
 	boundinfo->nindexes = greatest_modulus;
 	boundinfo->indexes = (int *) palloc(greatest_modulus * sizeof(int));
 	for (i = 0; i < greatest_modulus; i++)
 		boundinfo->indexes[i] = -1;
 
+	boundDatums = (Datum *) palloc(nparts * 2 * sizeof(Datum));
+
 	/*
 	 * For hash partitioning, there are as many datums (modulus and remainder
 	 * pairs) as there are partitions.  Indexes are simply values ranging from
@@ -409,10 +409,10 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	 */
 	for (i = 0; i < nparts; i++)
 	{
-		int			modulus = hbounds[i]->modulus;
-		int			remainder = hbounds[i]->remainder;
+		int			modulus = hbounds[i].modulus;
+		int			remainder = hbounds[i].remainder;
 
-		boundinfo->datums[i] = (Datum *) palloc(2 * sizeof(Datum));
+		boundinfo->datums[i] = &boundDatums[i * 2];
 		boundinfo->datums[i][0] = Int32GetDatum(modulus);
 		boundinfo->datums[i][1] = Int32GetDatum(remainder);
 
@@ -424,8 +424,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 			remainder += modulus;
 		}
 
-		(*mapping)[hbounds[i]->index] = i;
-		pfree(hbounds[i]);
+		(*mapping)[hbounds[i].index] = i;
 	}
 	pfree(hbounds);
 
@@ -3693,8 +3692,8 @@ partition_hash_bsearch(PartitionBoundInfo boundinfo,
 static int32
 qsort_partition_hbound_cmp(const void *a, const void *b)
 {
-	PartitionHashBound *h1 = (*(PartitionHashBound *const *) a);
-	PartitionHashBound *h2 = (*(PartitionHashBound *const *) b);
+	PartitionHashBound *const h1 = (PartitionHashBound *const) a;
+	PartitionHashBound *const h2 = (PartitionHashBound *const) b;
 
 	return partition_hbound_cmp(h1->modulus, h1->remainder,
 								h2->modulus, h2->remainder);
-- 
2.30.2

