From 99fe617f2e09955f1ef638b360bc7b819779b18f Mon Sep 17 00:00:00 2001
From: "yizhi.fzh" <yizhi.fzh@alibaba-inc.com>
Date: Sat, 24 Feb 2024 21:26:19 +0800
Subject: [PATCH v8 3/5] Use bitset instead of Bitmapset for pre_detoast_attrs

due to commit 00b41463c, when all the bits in a bitmapset is unset, the
memory under it will be released automatically, this is cause extra
overhead for shared-detoast-datum feature, so using bitset now.
---
 src/backend/executor/execExprInterp.c |  2 +-
 src/backend/executor/execTuples.c     |  8 ++++----
 src/include/executor/tuptable.h       | 17 ++++++++++++-----
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index dc0db12ff4..878235ae76 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -202,7 +202,7 @@ ExecSlotDetoastDatum(TupleTableSlot *slot, int attnum)
 																(struct varlena *) oldDatum));
 		Assert(slot->tts_nvalid > attnum);
 		Assert(oldDatum != slot->tts_values[attnum]);
-		slot->pre_detoasted_attrs = bms_add_member(slot->pre_detoasted_attrs, attnum);
+		bitset_add_member(slot->pre_detoasted_attrs, attnum);
 		MemoryContextSwitchTo(old);
 	}
 }
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 2d11e5e8b3..830e1d4ea6 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -179,7 +179,7 @@ tts_virtual_materialize(TupleTableSlot *slot)
 		if (att->attbyval || slot->tts_isnull[natt])
 			continue;
 
-		if (bms_is_member(natt, slot->pre_detoasted_attrs))
+		if (bitset_is_member(natt, slot->pre_detoasted_attrs))
 			/* it has been in slot->tts_mcxt already. */
 			continue;
 
@@ -1179,7 +1179,7 @@ MakeTupleTableSlot(TupleDesc tupleDesc,
 			 + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
 
 		PinTupleDesc(tupleDesc);
-		slot->pre_detoasted_attrs = NULL;
+		slot->pre_detoasted_attrs = bitset_init(tupleDesc->natts);
 	}
 	else
 		slot->pre_detoasted_attrs = NULL;
@@ -1339,7 +1339,7 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
 	if (slot->tts_isnull)
 		pfree(slot->tts_isnull);
 	if (slot->pre_detoasted_attrs)
-		bms_free(slot->pre_detoasted_attrs);
+		bitset_free(slot->pre_detoasted_attrs);
 
 	/*
 	 * Install the new descriptor; if it's refcounted, bump its refcount.
@@ -1357,7 +1357,7 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
 		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool));
 
 	old = MemoryContextSwitchTo(slot->tts_mcxt);
-	slot->pre_detoasted_attrs = NULL;
+	slot->pre_detoasted_attrs = bitset_init(tupdesc->natts);
 	MemoryContextSwitchTo(old);
 }
 
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 3951ffc495..8f3eba7fbb 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -138,9 +138,16 @@ typedef struct TupleTableSlot
 	 * TupleTableSlot.tts_mcxt and be clear whenever the tts_values[*] is
 	 * invalidated.
 	 *
+	 * Bitset rather than Bitmapset is chosen here because when all the
+	 * members of Bitmapset are deleted, the allocated memory will be
+	 * deallocated automatically, which is too expensive in this case since we
+	 * need to deleted all the members in each ExecClearTuple and repopulate
+	 * it again when fill the detoast datum to tts_values[*]. This situation
+	 * will be run again and again in an execution cycle.
+	 *
 	 * These values are populated by EEOP_{INNER/OUTER/SCAN}_VAR_TOAST steps.
 	 */
-	Bitmapset	   *pre_detoasted_attrs;
+	Bitset	   *pre_detoasted_attrs;
 } TupleTableSlot;
 
 /* routines for a TupleTableSlot implementation */
@@ -448,12 +455,12 @@ ExecFreePreDetoastDatum(TupleTableSlot *slot)
 	int			attnum;
 
 	attnum = -1;
-	while ((attnum = bms_next_member(slot->pre_detoasted_attrs, attnum)) >= 0)
+	while ((attnum = bitset_next_member(slot->pre_detoasted_attrs, attnum)) >= 0)
 	{
 		pfree((void *) slot->tts_values[attnum]);
 	}
 
-	slot->pre_detoasted_attrs = bms_del_members(slot->pre_detoasted_attrs, slot->pre_detoasted_attrs);
+	bitset_clear(slot->pre_detoasted_attrs);
 }
 
 
@@ -536,9 +543,9 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
 		int			attnum = -1;
 		MemoryContext old = MemoryContextSwitchTo(dstslot->tts_mcxt);
 
-		dstslot->pre_detoasted_attrs = bms_copy(srcslot->pre_detoasted_attrs);
+		dstslot->pre_detoasted_attrs = bitset_copy(srcslot->pre_detoasted_attrs);
 
-		while ((attnum = bms_next_member(dstslot->pre_detoasted_attrs, attnum)) >= 0)
+		while ((attnum = bitset_next_member(dstslot->pre_detoasted_attrs, attnum)) >= 0)
 		{
 			struct varlena *datum = (struct varlena *) srcslot->tts_values[attnum];
 			Size		len;
-- 
2.34.1

