From 105495d5aa6b25f61c812dd5cb9ff692abe38373 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com>
Date: Thu, 27 May 2021 13:37:32 +0530
Subject: [PATCH] test times and block counts

---
 src/backend/access/heap/hio.c             | 21 ++++++++++++
 src/backend/commands/createas.c           | 41 +++++++++++++++++++++++
 src/backend/storage/freespace/freespace.c | 22 +++++++++++-
 src/backend/storage/lmgr/lmgr.c           | 13 +++++++
 src/include/commands/createas.h           | 17 ++++++++++
 5 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index d34edb4190..d737c2d763 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -19,6 +19,8 @@
 #include "access/hio.h"
 #include "access/htup_details.h"
 #include "access/visibilitymap.h"
+#include "commands/createas.h"
+#include "portability/instr_time.h"
 #include "storage/bufmgr.h"
 #include "storage/freespace.h"
 #include "storage/lmgr.h"
@@ -198,12 +200,17 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
 				firstBlock = InvalidBlockNumber;
 	int			extraBlocks;
 	int			lockWaiters;
+	instr_time	start;
+	instr_time	end;
 
 	/* Use the length of the lock wait queue to judge how much to extend. */
 	lockWaiters = RelationExtensionLockWaiterCount(relation);
 	if (lockWaiters <= 0)
 		return;
 
+	if (is_ctas)
+		INSTR_TIME_SET_CURRENT(start);
+
 	/*
 	 * It might seem like multiplying the number of lock waiters by as much as
 	 * 20 is too aggressive, but benchmarking revealed that smaller numbers
@@ -212,6 +219,9 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
 	 */
 	extraBlocks = Min(512, lockWaiters * 20);
 
+	if (is_ctas)
+		bulk_rel_extension_blocks_count += extraBlocks;
+
 	do
 	{
 		Buffer		buffer;
@@ -267,6 +277,14 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
 	 * just inserted.
 	 */
 	FreeSpaceMapVacuumRange(relation, firstBlock, blockNum + 1);
+
+	if (is_ctas)
+	{
+		INSTR_TIME_SET_CURRENT(end);
+		INSTR_TIME_SUBTRACT(end, start);
+		rel_add_extra_blocks_time += INSTR_TIME_GET_MICROSEC(end);
+		bulk_rel_extension_count++;
+	}
 }
 
 /*
@@ -630,6 +648,9 @@ loop:
 	 */
 	page = BufferGetPage(buffer);
 
+	if (is_ctas)
+		single_block_rel_extension_count++;
+
 	if (!PageIsNew(page))
 		elog(ERROR, "page %u of relation \"%s\" should be empty but is not",
 			 BufferGetBlockNumber(buffer),
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 53ca3010c6..df23a72335 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -62,6 +62,14 @@ static bool intorel_receive(TupleTableSlot *slot, DestReceiver *self);
 static void intorel_shutdown(DestReceiver *self);
 static void intorel_destroy(DestReceiver *self);
 
+bool is_ctas = false;
+uint64 lock_rel_extension_time = 0;
+uint64 get_page_from_fsm_time = 0;
+uint64 rel_add_extra_blocks_time = 0;
+uint64 bulk_rel_extension_count = 0;
+uint64 single_block_rel_extension_count = 0;
+uint64 fsm_hit_count = 0;
+uint64 bulk_rel_extension_blocks_count = 0;
 
 /*
  * create_ctas_internal
@@ -482,6 +490,14 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 	ListCell   *lc;
 	int			attnum;
 
+	lock_rel_extension_time = 0;
+	get_page_from_fsm_time = 0;
+	rel_add_extra_blocks_time = 0;
+	bulk_rel_extension_count = 0;
+	single_block_rel_extension_count = 0;
+	fsm_hit_count = 0;
+	bulk_rel_extension_blocks_count = 0;
+
 	/*
 	 * All the necessary work such as table creation, sanity checks etc. would
 	 * have been done by the leader. So, parallel workers just need to open the
@@ -652,6 +668,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 	/* Nothing to insert if WITH NO DATA is specified. */
 	if (!myState->into->skipData)
 	{
+		is_ctas = true;
 		/*
 		 * Note that the input slot might not be of the type of the target
 		 * relation. That's supported by table_tuple_insert(), but slightly
@@ -665,6 +682,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 						   myState->output_cid,
 						   myState->ti_options,
 						   myState->bistate);
+		is_ctas = false;
 	}
 
 	/* We know this is a newly created relation, so there are no indexes */
@@ -690,6 +708,29 @@ intorel_shutdown(DestReceiver *self)
 	/* close rel, but keep lock until commit */
 	table_close(myState->rel, NoLock);
 	myState->rel = NULL;
+
+	ereport(LOG, (errmsg("Total time spent in LockRelationForExtension is %f msec",
+			(((double) lock_rel_extension_time) / 1000.0)), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total time spent in GetPageWithFreeSpace is %f msec",
+			(((double) get_page_from_fsm_time) / 1000.0)), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total time spent in RelationAddExtraBlocks is %f msec",
+			(((double) rel_add_extra_blocks_time) / 1000.0)), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total number of times extended the relation in bulk is %lu",
+			bulk_rel_extension_count), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total number of blocks added in bulk extension is %lu",
+			bulk_rel_extension_blocks_count), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total number of times extended the relation by one block is %lu",
+			single_block_rel_extension_count), errhidestmt(true)));
+	ereport(LOG, (errmsg("Total number of times getting the page from FSM is %lu",
+			fsm_hit_count), errhidestmt(true)));
+
+	lock_rel_extension_time = 0;
+	get_page_from_fsm_time = 0;
+	rel_add_extra_blocks_time = 0;
+	bulk_rel_extension_count = 0;
+	single_block_rel_extension_count = 0;
+	fsm_hit_count = 0;
+	bulk_rel_extension_blocks_count = 0;
 }
 
 /*
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index 8c12dda238..518170a790 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -25,7 +25,9 @@
 
 #include "access/htup_details.h"
 #include "access/xlogutils.h"
+#include "commands/createas.h"
 #include "miscadmin.h"
+#include "portability/instr_time.h"
 #include "storage/freespace.h"
 #include "storage/fsm_internals.h"
 #include "storage/lmgr.h"
@@ -132,8 +134,26 @@ BlockNumber
 GetPageWithFreeSpace(Relation rel, Size spaceNeeded)
 {
 	uint8		min_cat = fsm_space_needed_to_cat(spaceNeeded);
+	BlockNumber blk_no;
+	instr_time	start;
+	instr_time	end;
 
-	return fsm_search(rel, min_cat);
+	if (is_ctas)
+		INSTR_TIME_SET_CURRENT(start);
+
+	blk_no = fsm_search(rel, min_cat);
+
+	if (is_ctas)
+	{
+		INSTR_TIME_SET_CURRENT(end);
+		INSTR_TIME_SUBTRACT(end, start);
+		get_page_from_fsm_time += INSTR_TIME_GET_MICROSEC(end);
+
+		if (blk_no != InvalidBlockNumber)
+			fsm_hit_count++;
+	}
+
+	return blk_no;
 }
 
 /*
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index cdf2266d6d..bed87898ae 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -19,6 +19,7 @@
 #include "access/transam.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
+#include "commands/createas.h"
 #include "commands/progress.h"
 #include "miscadmin.h"
 #include "pgstat.h"
@@ -403,12 +404,24 @@ void
 LockRelationForExtension(Relation relation, LOCKMODE lockmode)
 {
 	LOCKTAG		tag;
+	instr_time	start;
+	instr_time	end;
+
+	if (is_ctas)
+		INSTR_TIME_SET_CURRENT(start);
 
 	SET_LOCKTAG_RELATION_EXTEND(tag,
 								relation->rd_lockInfo.lockRelId.dbId,
 								relation->rd_lockInfo.lockRelId.relId);
 
 	(void) LockAcquire(&tag, lockmode, false, false);
+
+	if (is_ctas)
+	{
+		INSTR_TIME_SET_CURRENT(end);
+		INSTR_TIME_SUBTRACT(end, start);
+		lock_rel_extension_time += INSTR_TIME_GET_MICROSEC(end);
+	}
 }
 
 /*
diff --git a/src/include/commands/createas.h b/src/include/commands/createas.h
index 74022aab41..6f998c6146 100644
--- a/src/include/commands/createas.h
+++ b/src/include/commands/createas.h
@@ -21,6 +21,23 @@
 #include "tcop/dest.h"
 #include "utils/queryenvironment.h"
 
+extern bool is_ctas;
+/* time spent in LockRelationForExtension */
+extern uint64 lock_rel_extension_time;
+/* time spent in GetPageWithFreeSpace */
+extern uint64 get_page_from_fsm_time;
+ /* time spent in RelationAddExtraBlocks */
+extern uint64 rel_add_extra_blocks_time;
+/* number of times each worker extended the relation in bulk */
+extern uint64 bulk_rel_extension_count;
+/* number of times each worker extended the relation by one block */
+extern uint64 single_block_rel_extension_count;
+/* number of times each worker gets the page from FSM */
+extern uint64 fsm_hit_count;
+/* number of blocks added in bulk extension */
+extern uint64 bulk_rel_extension_blocks_count;
+
+
 typedef struct
 {
 	DestReceiver pub;			/* publicly-known function pointers */
-- 
2.25.1

