commit b269c5eb3ca039f3a9b7b59878b1a575a97ba607 Author: Masahiko Sawada Date: Mon Mar 2 14:05:02 2026 -0800 Proposed changes for 0003 patch. diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 70882544d05..644739483c8 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -2436,10 +2436,8 @@ vacuum_delay_point(bool is_analyze) if (IsParallelWorker()) { /* - * Possibly update cost-based delay parameters. - * - * Do it before checking VacuumCostActive, because its value might be - * changed after calling this function. + * Update cost-based delay parameters for a parallel autovacuum worker + * if any changes are detected. */ parallel_vacuum_update_shared_delay_params(); } @@ -2460,8 +2458,8 @@ vacuum_delay_point(bool is_analyze) VacuumUpdateCosts(); /* - * If we are parallel autovacuum leader and some of cost-based - * parameters had changed, let other parallel workers know. + * Propagate cost-based parameters to shared memory if any of them + * have changed during the config reload. */ parallel_vacuum_propagate_shared_delay_params(); } diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 80b57bf9da3..c411ded2e7f 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -18,6 +18,13 @@ * the parallel context is re-initialized so that the same DSM can be used for * multiple passes of index bulk-deletion and index cleanup. * + * For parallel autovacuum, we need to propagate cost-based delay parameters + * from the leader to its workers, as the leader's parameters can change + * even while processing a table (e.g., due to a config reload). + * The PVSharedCostParams struct manages these parameters using a + * generation counter. Each parallel worker polls this shared state and + * refreshes its local delay parameters whenever a change is detected. + * * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -54,26 +61,6 @@ #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 VacuumCostParams -{ - double cost_delay; - int cost_limit; - int cost_page_dirty; - int cost_page_hit; - int cost_page_miss; -} VacuumCostParams; - -#define FillVacCostParams(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 - /* * Struct for cost-based vacuum delay related parameters to share among an * autovacuum worker and its parallel vacuum workers. @@ -81,23 +68,22 @@ typedef struct VacuumCostParams 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. + * The generation counter is incremented by the leader process each time + * it updates the shared cost-based parameters. Paralell vacuum workers + * compare this with their local generation, + * shared_params_generation_localto, detect if they need to refresh their + * local parameter copies. */ pg_atomic_uint32 generation; slock_t mutex; /* protects all fields below */ - /* - * Copies of the corresponding cost-based vacuum delay parameters from - * autovacuum leader process. - */ - VacuumCostParams params_data; + /* Parameters to share with parallel workers */ + double cost_delay; + int cost_limit; + int cost_page_dirty; + int cost_page_hit; + int cost_page_miss; } PVSharedCostParams; /* @@ -285,7 +271,7 @@ struct ParallelVacuumState static PVSharedCostParams *pv_shared_cost_params = NULL; -/* See comments for the PVSharedCostParams structure for the explanation. */ +/* See comments in the PVSharedCostParams for deatils */ static uint32 shared_params_generation_local = 0; static int parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int nrequested, @@ -299,6 +285,7 @@ static void parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation static bool parallel_vacuum_index_is_parallel_safe(Relation indrel, int num_index_scans, bool vacuum); static void parallel_vacuum_error_callback(void *arg); +static inline void parallel_vacuum_set_cost_parameters(PVSharedCostParams *params); /* * Try to enter parallel mode and create a parallel context. Then initialize @@ -461,9 +448,10 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, shared->is_autovacuum = AmAutoVacuumWorkerProcess(); + /* Initialize shared cost-based parameters if it's for autovacuum */ if (shared->is_autovacuum) { - FillVacCostParams(&shared->cost_params.params_data); + parallel_vacuum_set_cost_parameters(&shared->cost_params); pg_atomic_init_u32(&shared->cost_params.generation, 0); SpinLockInit(&shared->cost_params.mutex); @@ -615,10 +603,21 @@ parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, long num_table_tup } /* - * If we are parallel *autovacuum* worker, check whether related to cost-based - * vacuum delay parameters had changed in the leader worker. If so, - * corresponding parameters will be updated to the values which leader worker - * is operating on. + * Set cost-based delay parameter values to the given 'params'. + */ +static inline void +parallel_vacuum_set_cost_parameters(PVSharedCostParams *params) +{ + params->cost_delay = vacuum_cost_delay; + params->cost_limit = vacuum_cost_limit; + params->cost_page_dirty = VacuumCostPageDirty; + params->cost_page_hit = VacuumCostPageHit; + params->cost_page_miss = VacuumCostPageMiss; +} + +/* + * Updates the cost-based vacuum delay parameters for parallel vacuum workers + * launched by an autovacuum worker. * * For non-autovacuum parallel worker this function will have no effect. */ @@ -629,7 +628,7 @@ parallel_vacuum_update_shared_delay_params(void) Assert(IsParallelWorker()); - /* Check whether we are running parallel autovacuum */ + /* Quick return if the wokrer is not running for the autovacuum */ if (pv_shared_cost_params == NULL) return; @@ -641,13 +640,11 @@ parallel_vacuum_update_shared_delay_params(void) return; SpinLockAcquire(&pv_shared_cost_params->mutex); - - VacuumCostDelay = pv_shared_cost_params->params_data.cost_delay; - VacuumCostLimit = pv_shared_cost_params->params_data.cost_limit; - VacuumCostPageDirty = pv_shared_cost_params->params_data.cost_page_dirty; - VacuumCostPageHit = pv_shared_cost_params->params_data.cost_page_hit; - VacuumCostPageMiss = pv_shared_cost_params->params_data.cost_page_miss; - + VacuumCostDelay = pv_shared_cost_params->cost_delay; + VacuumCostLimit = pv_shared_cost_params->cost_limit; + VacuumCostPageDirty = pv_shared_cost_params->cost_page_dirty; + VacuumCostPageHit = pv_shared_cost_params->cost_page_hit; + VacuumCostPageMiss = pv_shared_cost_params->cost_page_miss; SpinLockRelease(&pv_shared_cost_params->mutex); VacuumUpdateCosts(); @@ -656,46 +653,41 @@ parallel_vacuum_update_shared_delay_params(void) } /* - * Function to be called from parallel autovacuum leader in order to propagate - * some cost-based vacuum delay parameters to the supportive workers. + * Store the cost-based vacuum delay parameters on the shared memory so that + * parallel vacuum workers can reflect them (see + * parallel_vacuum_update_shared_delay_params()). */ void parallel_vacuum_propagate_shared_delay_params(void) { - VacuumCostParams *params_data; - Assert(AmAutoVacuumWorkerProcess()); - /* Check whether we are running parallel autovacuum */ + /* + * Quick return if the leader process is not shareing the delay + * parameters. + */ if (pv_shared_cost_params == NULL) return; /* - * Only leader worker can modify this shared structure, so we can read it - * without acquiring a lock. + * Check if any delay parameters has changed. We can read them without + * locks as only the leader can modify them. */ - params_data = &pv_shared_cost_params->params_data; - - if (vacuum_cost_delay == params_data->cost_delay && - vacuum_cost_limit == params_data->cost_limit && - VacuumCostPageDirty == params_data->cost_page_dirty && - VacuumCostPageHit == params_data->cost_page_hit && - VacuumCostPageMiss == params_data->cost_page_miss) - { - /* - * We don't need to update shared cost-based vacuum delay params if - * they haven't changed. - */ + if (vacuum_cost_delay == pv_shared_cost_params->cost_delay && + vacuum_cost_limit == pv_shared_cost_params->cost_limit && + VacuumCostPageDirty == pv_shared_cost_params->cost_page_dirty && + VacuumCostPageHit == pv_shared_cost_params->cost_page_hit && + VacuumCostPageMiss == pv_shared_cost_params->cost_page_miss) return; - } + /* Update the shared delay parameters */ SpinLockAcquire(&pv_shared_cost_params->mutex); - FillVacCostParams(&pv_shared_cost_params->params_data); + parallel_vacuum_set_cost_parameters(&pv_shared_cost_params); 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. + * Increment the 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); } diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index de9f576e0f3..1120646f2c8 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3250,7 +3250,6 @@ VacAttrStatsP VacDeadItemsInfo VacErrPhase VacOptValue -VacuumCostParams VacuumParams VacuumRelation VacuumStmt