0002-Remove-BackgroundWorkerStateChange-s-inner-loop.patch
text/x-patch
Filename: 0002-Remove-BackgroundWorkerStateChange-s-inner-loop.patch
Type: text/x-patch
Part: 1
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