mirror of
https://github.com/postgres/postgres.git
synced 2025-08-30 06:01:21 +03:00
Add max_parallel_workers GUC.
Increase the default value of the existing max_worker_processes GUC from 8 to 16, and add a new max_parallel_workers GUC with a maximum of 8. This way, even if the maximum amount of parallel query is happening, there is still room for background workers that do other things, as originally envisioned when max_worker_processes was added. Julien Rouhaud, reviewed by Amit Kapila and by revised by me.
This commit is contained in:
@@ -80,9 +80,22 @@ typedef struct BackgroundWorkerSlot
|
||||
BackgroundWorker worker;
|
||||
} BackgroundWorkerSlot;
|
||||
|
||||
/*
|
||||
* In order to limit the total number of parallel workers (according to
|
||||
* max_parallel_workers GUC), we maintain the number of active parallel
|
||||
* workers. Since the postmaster cannot take locks, two variables are used for
|
||||
* this purpose: the number of registered parallel workers (modified by the
|
||||
* backends, protected by BackgroundWorkerLock) and the number of terminated
|
||||
* parallel workers (modified only by the postmaster, lockless). The active
|
||||
* number of parallel workers is the number of registered workers minus the
|
||||
* terminated ones. These counters can of course overflow, but it's not
|
||||
* important here since the subtraction will still give the right number.
|
||||
*/
|
||||
typedef struct BackgroundWorkerArray
|
||||
{
|
||||
int total_slots;
|
||||
uint32 parallel_register_count;
|
||||
uint32 parallel_terminate_count;
|
||||
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER];
|
||||
} BackgroundWorkerArray;
|
||||
|
||||
@@ -127,6 +140,8 @@ BackgroundWorkerShmemInit(void)
|
||||
int slotno = 0;
|
||||
|
||||
BackgroundWorkerData->total_slots = max_worker_processes;
|
||||
BackgroundWorkerData->parallel_register_count = 0;
|
||||
BackgroundWorkerData->parallel_terminate_count = 0;
|
||||
|
||||
/*
|
||||
* Copy contents of worker list into shared memory. Record the shared
|
||||
@@ -267,9 +282,12 @@ BackgroundWorkerStateChange(void)
|
||||
|
||||
/*
|
||||
* We need a memory barrier here to make sure that the load of
|
||||
* bgw_notify_pid completes before the store to in_use.
|
||||
* bgw_notify_pid and the update of parallel_terminate_count
|
||||
* complete before the store to in_use.
|
||||
*/
|
||||
notify_pid = slot->worker.bgw_notify_pid;
|
||||
if ((slot->worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
|
||||
BackgroundWorkerData->parallel_terminate_count++;
|
||||
pg_memory_barrier();
|
||||
slot->pid = 0;
|
||||
slot->in_use = false;
|
||||
@@ -370,6 +388,9 @@ ForgetBackgroundWorker(slist_mutable_iter *cur)
|
||||
|
||||
Assert(rw->rw_shmem_slot < max_worker_processes);
|
||||
slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
|
||||
if ((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
|
||||
BackgroundWorkerData->parallel_terminate_count++;
|
||||
|
||||
slot->in_use = false;
|
||||
|
||||
ereport(DEBUG1,
|
||||
@@ -824,6 +845,7 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
|
||||
{
|
||||
int slotno;
|
||||
bool success = false;
|
||||
bool parallel;
|
||||
uint64 generation = 0;
|
||||
|
||||
/*
|
||||
@@ -840,8 +862,27 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
|
||||
if (!SanityCheckBackgroundWorker(worker, ERROR))
|
||||
return false;
|
||||
|
||||
parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
|
||||
|
||||
LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
|
||||
|
||||
/*
|
||||
* If this is a parallel worker, check whether there are already too many
|
||||
* parallel workers; if so, don't register another one. Our view of
|
||||
* parallel_terminate_count may be slightly stale, but that doesn't really
|
||||
* matter: we would have gotten the same result if we'd arrived here
|
||||
* slightly earlier anyway. There's no help for it, either, since the
|
||||
* postmaster must not take locks; a memory barrier wouldn't guarantee
|
||||
* anything useful.
|
||||
*/
|
||||
if (parallel && (BackgroundWorkerData->parallel_register_count -
|
||||
BackgroundWorkerData->parallel_terminate_count) >=
|
||||
max_parallel_workers)
|
||||
{
|
||||
LWLockRelease(BackgroundWorkerLock);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for an unused slot. If we find one, grab it.
|
||||
*/
|
||||
@@ -856,6 +897,8 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
|
||||
slot->generation++;
|
||||
slot->terminate = false;
|
||||
generation = slot->generation;
|
||||
if (parallel)
|
||||
BackgroundWorkerData->parallel_register_count++;
|
||||
|
||||
/*
|
||||
* Make sure postmaster doesn't see the slot as in use before it
|
||||
|
Reference in New Issue
Block a user