0002-Remove-BackgroundWorkerStateChange-s-inner-loop.patch

text/x-patch

Filename: 0002-Remove-BackgroundWorkerStateChange-s-inner-loop.patch
Type: text/x-patch
Part: 1
Message: Re: connection establishment versus parallel workers

Patch

Format: format-patch
Series: patch 0002
Subject: Remove BackgroundWorkerStateChange()'s inner loop.
File+
src/backend/postmaster/bgworker.c 33 10
From 5b41df0db817970ca2278a6354cc0790cd565a0c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 31 Dec 2024 17:44:54 +1300
Subject: [PATCH 2/3] Remove BackgroundWorkerStateChange()'s inner loop.

Previously, when processing a slot that might have changed, the
postmaster would scan the list of registered background workers looking
for the one using that slot.

Maintain a table in postmaster private memory that can be used to find
entries by slot number.

Discussion: https://postgr.es/m/Z1n5UpAiGDmFcMmd%40nathan
---
 src/backend/postmaster/bgworker.c | 43 ++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 0de0422bb53..3e326e48540 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -39,6 +39,13 @@
  */
 dlist_head	BackgroundWorkerList = DLIST_STATIC_INIT(BackgroundWorkerList);
 
+/*
+ * An array of registered background workers indexed by slot number.
+ * BackgroundWorkerList entries are also in this table for fast lookup, and
+ * must be kept in sync.
+ */
+static RegisteredBgWorker **BackgroundWorkerTable;
+
 /*
  * BackgroundWorkerSlots exist in shared memory and can be accessed (via
  * the BackgroundWorkerArray) by both the postmaster and by regular backends.
@@ -202,6 +209,19 @@ BackgroundWorkerShmemInit(void)
 		BackgroundWorkerData->change_queue_head = 0;
 		BackgroundWorkerData->change_queue_tail = 0;
 
+		/*
+		 * Allocate an array to let us find RegisteredBgWorker objects by slot
+		 * number.
+		 *
+		 * XXX Where else could this allocation happen?
+		 */
+		if (PostmasterContext && !BackgroundWorkerTable)
+			BackgroundWorkerTable =
+				MemoryContextAllocExtended(PostmasterContext,
+										   sizeof(BackgroundWorkerTable[0]) *
+										   max_worker_processes,
+										   MCXT_ALLOC_ZERO);
+
 		/*
 		 * Copy contents of worker list into shared memory.  Record the shared
 		 * memory slot assigned to each worker.  This ensures a 1-to-1
@@ -223,6 +243,9 @@ BackgroundWorkerShmemInit(void)
 			rw->rw_worker.bgw_notify_pid = 0;	/* might be reinit after crash */
 			memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
 
+			/* Add to slot-number lookup table. */
+			BackgroundWorkerTable[rw->rw_shmem_slot] = rw;
+
 			/* Enqueue change notifications for all populated slots. */
 			BackgroundWorkerData->change_queue[BackgroundWorkerData->change_queue_head++] = slotno;
 
@@ -252,18 +275,11 @@ BackgroundWorkerShmemInit(void)
 static RegisteredBgWorker *
 FindRegisteredWorkerBySlotNumber(int slotno)
 {
-	dlist_iter	iter;
+	RegisteredBgWorker *rw = BackgroundWorkerTable[slotno];
 
-	dlist_foreach(iter, &BackgroundWorkerList)
-	{
-		RegisteredBgWorker *rw;
-
-		rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
-		if (rw->rw_shmem_slot == slotno)
-			return rw;
-	}
+	Assert(!rw || rw->rw_shmem_slot == slotno);
 
-	return NULL;
+	return rw;
 }
 
 /*
@@ -487,6 +503,9 @@ BackgroundWorkerStateChange(bool allow_new_workers)
 								 rw->rw_worker.bgw_name)));
 
 		dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
+
+		/* Add to slot-number lookup table. */
+		BackgroundWorkerTable[rw->rw_shmem_slot] = rw;
 	}
 }
 
@@ -551,6 +570,10 @@ ForgetBackgroundWorker(RegisteredBgWorker *rw)
 	slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
 	Assert(slot->in_use);
 
+	/* Remove from slot-number lookup table. */
+	Assert(BackgroundWorkerTable[rw->rw_shmem_slot] == rw);
+	BackgroundWorkerTable[rw->rw_shmem_slot] = NULL;
+
 	/*
 	 * We need a memory barrier here to make sure that the update of
 	 * parallel_terminate_count completes before the store to in_use.
-- 
2.47.1