v21-0003-Cost-based-parameters-propagation-for-parallel-a.patch
text/x-patch
Filename: v21-0003-Cost-based-parameters-propagation-for-parallel-a.patch
Type: text/x-patch
Part: 4
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v21-0003
Subject: Cost based parameters propagation for parallel autovacuum
| File | + | − |
|---|---|---|
| src/backend/commands/vacuum.c | 21 | 2 |
| src/backend/commands/vacuumparallel.c | 164 | 0 |
| src/backend/postmaster/autovacuum.c | 1 | 1 |
| src/include/commands/vacuum.h | 2 | 0 |
| src/tools/pgindent/typedefs.list | 2 | 0 |
From 21cbbbe37e36b53ac70b9827296a3430aba4680f Mon Sep 17 00:00:00 2001
From: Daniil Davidov <d.davydov@postgrespro.ru>
Date: Thu, 15 Jan 2026 23:15:48 +0700
Subject: [PATCH v21 3/5] Cost based parameters propagation for parallel
autovacuum
---
src/backend/commands/vacuum.c | 23 +++-
src/backend/commands/vacuumparallel.c | 164 ++++++++++++++++++++++++++
src/backend/postmaster/autovacuum.c | 2 +-
src/include/commands/vacuum.h | 2 +
src/tools/pgindent/typedefs.list | 2 +
5 files changed, 190 insertions(+), 3 deletions(-)
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 03932f45c8a..70882544d05 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -2430,8 +2430,21 @@ vacuum_delay_point(bool is_analyze)
/* Always check for interrupts */
CHECK_FOR_INTERRUPTS();
- if (InterruptPending ||
- (!VacuumCostActive && !ConfigReloadPending))
+ if (InterruptPending)
+ return;
+
+ if (IsParallelWorker())
+ {
+ /*
+ * Possibly update cost-based delay parameters.
+ *
+ * Do it before checking VacuumCostActive, because its value might be
+ * changed after calling this function.
+ */
+ parallel_vacuum_update_shared_delay_params();
+ }
+
+ if (!VacuumCostActive && !ConfigReloadPending)
return;
/*
@@ -2445,6 +2458,12 @@ vacuum_delay_point(bool is_analyze)
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
VacuumUpdateCosts();
+
+ /*
+ * If we are parallel autovacuum leader and some of cost-based
+ * parameters had changed, let other parallel workers know.
+ */
+ parallel_vacuum_propagate_shared_delay_params();
}
/*
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 86d9f2b74c9..ccb3812165c 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -53,6 +53,56 @@
#define PARALLEL_VACUUM_KEY_WAL_USAGE 4
#define PARALLEL_VACUUM_KEY_INDEX_STATS 5
+/*
+ * Helper for the PVSharedCostParams structure (see below), to avoid
+ * repetition.
+ */
+typedef struct CostParamsData
+{
+ double cost_delay;
+ int cost_limit;
+ int cost_page_dirty;
+ int cost_page_hit;
+ int cost_page_miss;
+} CostParamsData;
+
+#define FillCostParamsData(cost_params) \
+ (cost_params)->cost_delay = vacuum_cost_delay; \
+ (cost_params)->cost_limit = vacuum_cost_limit; \
+ (cost_params)->cost_page_dirty = VacuumCostPageDirty; \
+ (cost_params)->cost_page_hit = VacuumCostPageHit; \
+ (cost_params)->cost_page_miss = VacuumCostPageMiss
+
+#define CostParamsDataEqual(params_1, params_2) \
+ ((params_1).cost_delay == (params_2).cost_delay && \
+ (params_1).cost_limit == (params_2).cost_limit && \
+ (params_1).cost_page_dirty == (params_2).cost_page_dirty && \
+ (params_1).cost_page_hit == (params_2).cost_page_hit && \
+ (params_1).cost_page_miss == (params_2).cost_page_miss)
+
+/*
+ * Struct for cost-based vacuum delay related parameters to share among an
+ * autovacuum worker and its parallel vacuum workers.
+ */
+typedef struct PVSharedCostParams
+{
+ /*
+ * Each time leader worker updates its parameters, it must increase
+ * generation. Every parallel worker keeps the generation
+ * (shared_params_local_generation) at which it had last time received
+ * parameters from the leader.
+ *
+ * It is enough for worker to compare it's local_generation with the field
+ * below to determine whether it needs to receive new parameters' values.
+ */
+ pg_atomic_uint32 generation;
+
+ slock_t mutex; /* protects all fields below */
+
+ /* Copies of corresponding parameters from autovacuum leader process */
+ CostParamsData params_data;
+} PVSharedCostParams;
+
/*
* Shared information among parallel workers. So this is allocated in the DSM
* segment.
@@ -122,6 +172,18 @@ typedef struct PVShared
/* Statistics of shared dead items */
VacDeadItemsInfo dead_items_info;
+
+ /*
+ * If 'true' then we are running parallel autovacuum. Otherwise, we are
+ * running parallel maintenence VACUUM.
+ */
+ bool am_parallel_autovacuum;
+
+ /*
+ * Struct for syncing parameters between supportive parallel autovacuum
+ * workers with leader worker.
+ */
+ PVSharedCostParams cost_params;
} PVShared;
/* Status used during parallel index vacuum or cleanup */
@@ -224,6 +286,11 @@ struct ParallelVacuumState
PVIndVacStatus status;
};
+static PVSharedCostParams *pv_shared_cost_params = NULL;
+
+/* See comments for the PVSharedCostParams structure for the explanation. */
+static uint32 shared_params_generation_local = 0;
+
static int parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int nrequested,
bool *will_parallel_vacuum);
static void parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scans,
@@ -395,6 +462,17 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
pg_atomic_init_u32(&(shared->active_nworkers), 0);
pg_atomic_init_u32(&(shared->idx), 0);
+ shared->am_parallel_autovacuum = AmAutoVacuumWorkerProcess();
+
+ if (shared->am_parallel_autovacuum)
+ {
+ FillCostParamsData(&shared->cost_params.params_data);
+ pg_atomic_init_u32(&shared->cost_params.generation, 0);
+ SpinLockInit(&shared->cost_params.mutex);
+
+ pv_shared_cost_params = &(shared->cost_params);
+ }
+
shm_toc_insert(pcxt->toc, PARALLEL_VACUUM_KEY_SHARED, shared);
pvs->shared = shared;
@@ -539,6 +617,89 @@ parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, long num_table_tup
&wusage->cleanup);
}
+/*
+ * If we are parallel *autovacuum* worker, check whether related to
+ * cost-based delay parameters had changed in the leader worker. If
+ * so, corresponding parameters will be updated to the values which
+ * leader worker is operating on.
+ *
+ * For non-autovacuum parallel worker this function will have no effect.
+ */
+void
+parallel_vacuum_update_shared_delay_params(void)
+{
+ uint32 params_generation;
+ CostParamsData shared_params_data;
+
+ Assert(IsParallelWorker());
+
+ /* Check whether we are running parallel autovacuum */
+ if (pv_shared_cost_params == NULL)
+ return;
+
+ params_generation = pg_atomic_read_u32(&pv_shared_cost_params->generation);
+ Assert(shared_params_generation_local <= params_generation);
+
+ /* Return if parameters had not changed in the leader */
+ if (params_generation == shared_params_generation_local)
+ return;
+
+ SpinLockAcquire(&pv_shared_cost_params->mutex);
+
+ shared_params_data = pv_shared_cost_params->params_data;
+
+ VacuumCostDelay = shared_params_data.cost_delay;
+ VacuumCostLimit = shared_params_data.cost_limit;
+ VacuumCostPageDirty = shared_params_data.cost_page_dirty;
+ VacuumCostPageHit = shared_params_data.cost_page_hit;
+ VacuumCostPageMiss = shared_params_data.cost_page_miss;
+
+ SpinLockRelease(&pv_shared_cost_params->mutex);
+
+ VacuumUpdateCosts();
+
+ shared_params_generation_local = params_generation;
+}
+
+/*
+ * Function to be called from parallel autovacuum leader in order to propagate
+ * some cost-based parameters to the supportive workers.
+ */
+void
+parallel_vacuum_propagate_shared_delay_params(void)
+{
+ CostParamsData local_params_data;
+
+ Assert(AmAutoVacuumWorkerProcess());
+
+ /* Check whether we are running parallel autovacuum */
+ if (pv_shared_cost_params == NULL)
+ return;
+
+ FillCostParamsData(&local_params_data);
+ SpinLockAcquire(&pv_shared_cost_params->mutex);
+
+ if (CostParamsDataEqual(pv_shared_cost_params->params_data,
+ local_params_data))
+ {
+ /*
+ * We don't need to update shared delay params if they haven't
+ * changed.
+ */
+ SpinLockRelease(&pv_shared_cost_params->mutex);
+ return;
+ }
+
+ FillCostParamsData(&pv_shared_cost_params->params_data);
+ SpinLockRelease(&pv_shared_cost_params->mutex);
+
+ /*
+ * Increase generation of the parameters, i.e. let parallel workers know
+ * that they should re-read shared cost params.
+ */
+ pg_atomic_fetch_add_u32(&pv_shared_cost_params->generation, 1);
+}
+
/*
* Compute the number of parallel worker processes to request. Both index
* vacuum and index cleanup can be executed with parallel workers.
@@ -1105,6 +1266,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
VacuumSharedCostBalance = &(shared->cost_balance);
VacuumActiveNWorkers = &(shared->active_nworkers);
+ if (shared->am_parallel_autovacuum)
+ pv_shared_cost_params = &(shared->cost_params);
+
/* Set parallel vacuum state */
pvs.indrels = indrels;
pvs.nindexes = nindexes;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f40abe90ed5..0d78d02bd09 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1690,7 +1690,7 @@ VacuumUpdateCosts(void)
}
else
{
- /* Must be explicit VACUUM or ANALYZE */
+ /* Must be explicit VACUUM or ANALYZE or parallel autovacuum worker */
vacuum_cost_delay = VacuumCostDelay;
vacuum_cost_limit = VacuumCostLimit;
}
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index d3dc4e8cc67..b10829a9379 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -423,6 +423,8 @@ extern void parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs,
int num_index_scans,
bool estimated_count,
PVWorkersUsage *wusage);
+extern void parallel_vacuum_update_shared_delay_params(void);
+extern void parallel_vacuum_propagate_shared_delay_params(void);
extern void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc);
/* in commands/analyze.c */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index d84308c87ad..d00b57d3186 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -544,6 +544,7 @@ CopyToRoutine
CopyToState
CopyToStateData
Cost
+CostParamsData
CostSelector
Counters
CoverExt
@@ -2067,6 +2068,7 @@ PVIndStats
PVIndVacStatus
PVOID
PVShared
+PVSharedCostParams
PVWorkersUsage
PVWorkersStats
PX_Alias
--
2.43.0