aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/parallel.c3
-rw-r--r--src/backend/postmaster/bgworker.c45
-rw-r--r--src/backend/utils/init/globals.c3
-rw-r--r--src/backend/utils/misc/guc.c12
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample3
-rw-r--r--src/bin/pg_resetxlog/pg_resetxlog.c4
-rw-r--r--src/include/miscadmin.h1
-rw-r--r--src/include/postmaster/bgworker.h9
8 files changed, 73 insertions, 7 deletions
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 59dc3949d83..1c32fcd046c 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -454,7 +454,8 @@ LaunchParallelWorkers(ParallelContext *pcxt)
snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
MyProcPid);
worker.bgw_flags =
- BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
+ BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
+ | BGWORKER_CLASS_PARALLEL;
worker.bgw_start_time = BgWorkerStart_ConsistentState;
worker.bgw_restart_time = BGW_NEVER_RESTART;
worker.bgw_main = ParallelWorkerMain;
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 92495850db0..13a6e23a142 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -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,9 +862,28 @@ 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.
*/
for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
@@ -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
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index f23208353c3..c564ae396da 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -121,7 +121,8 @@ int replacement_sort_tuples = 150000;
*/
int NBuffers = 1000;
int MaxConnections = 90;
-int max_worker_processes = 8;
+int max_worker_processes = 16;
+int max_parallel_workers = 8;
int MaxBackends = 0;
int VacuumCostPageHit = 1; /* GUC parameters for vacuum */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 28ebcb6f3fa..4e49d5b79cc 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2477,7 +2477,7 @@ static struct config_int ConfigureNamesInt[] =
NULL,
},
&max_worker_processes,
- 8, 0, MAX_BACKENDS,
+ 16, 0, MAX_BACKENDS,
check_max_worker_processes, NULL, NULL
},
@@ -2665,6 +2665,16 @@ static struct config_int ConfigureNamesInt[] =
},
{
+ {"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
+ gettext_noop("Sets the maximum number of parallel workers than can be active at one time."),
+ NULL
+ },
+ &max_parallel_workers,
+ 8, 0, 1024,
+ NULL, NULL, NULL
+ },
+
+ {
{"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 0df15380a9a..1f490c7de4f 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -161,8 +161,9 @@
# - Asynchronous Behavior -
#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching
-#max_worker_processes = 8 # (change requires restart)
+#max_worker_processes = 16 # (change requires restart)
#max_parallel_workers_per_gather = 2 # taken from max_worker_processes
+#max_parallel_workers = 8 # total maximum number of worker_processes
#old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate
# (change requires restart)
#backend_flush_after = 0 # measured in pages, 0 disables
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 2b76f640797..1beee7f8eb8 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -584,7 +584,7 @@ GuessControlValues(void)
ControlFile.wal_log_hints = false;
ControlFile.track_commit_timestamp = false;
ControlFile.MaxConnections = 100;
- ControlFile.max_worker_processes = 8;
+ ControlFile.max_worker_processes = 16;
ControlFile.max_prepared_xacts = 0;
ControlFile.max_locks_per_xact = 64;
@@ -800,7 +800,7 @@ RewriteControlFile(void)
ControlFile.wal_log_hints = false;
ControlFile.track_commit_timestamp = false;
ControlFile.MaxConnections = 100;
- ControlFile.max_worker_processes = 8;
+ ControlFile.max_worker_processes = 16;
ControlFile.max_prepared_xacts = 0;
ControlFile.max_locks_per_xact = 64;
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 78c99543656..d06eca54b46 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -157,6 +157,7 @@ extern PGDLLIMPORT int NBuffers;
extern int MaxBackends;
extern int MaxConnections;
extern int max_worker_processes;
+extern int max_parallel_workers;
extern PGDLLIMPORT int MyProcPid;
extern PGDLLIMPORT pg_time_t MyStartTime;
diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h
index b6889a33200..b46d5818e79 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -58,6 +58,15 @@
*/
#define BGWORKER_BACKEND_DATABASE_CONNECTION 0x0002
+/*
+ * This class is used internally for parallel queries, to keep track of the
+ * number of active parallel workers and make sure we never launch more than
+ * max_parallel_workers parallel workers at the same time. Third party
+ * background workers should not use this class.
+ */
+#define BGWORKER_CLASS_PARALLEL 0x0010
+/* add additional bgworker classes here */
+
typedef void (*bgworker_main_type) (Datum main_arg);