*** a/src/backend/postmaster/autovacuum.c --- b/src/backend/postmaster/autovacuum.c *************** *** 224,229 **** typedef struct WorkerInfoData --- 224,230 ---- PGPROC *wi_proc; TimestampTz wi_launchtime; int wi_cost_delay; + int wi_cost_delay_base; int wi_cost_limit; int wi_cost_limit_base; } WorkerInfoData; *************** *** 1760,1825 **** autovac_balance_cost(void) * The idea here is that we ration out I/O equally. The amount of I/O * that a worker can consume is determined by cost_limit/cost_delay, so we * try to equalize those ratios rather than the raw limit settings. - * - * note: in cost_limit, zero also means use value from elsewhere, because - * zero is not a valid value. */ ! int vac_cost_limit = (autovacuum_vac_cost_limit > 0 ? ! autovacuum_vac_cost_limit : VacuumCostLimit); ! int vac_cost_delay = (autovacuum_vac_cost_delay >= 0 ? ! autovacuum_vac_cost_delay : VacuumCostDelay); ! double cost_total; ! double cost_avail; dlist_iter iter; - /* not set? nothing to do */ - if (vac_cost_limit <= 0 || vac_cost_delay <= 0) - return; - - /* caculate the total base cost limit of active workers */ - cost_total = 0.0; dlist_foreach(iter, &AutoVacuumShmem->av_runningWorkers) { WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur); if (worker->wi_proc != NULL && ! worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0) ! cost_total += ! (double) worker->wi_cost_limit_base / worker->wi_cost_delay; } - /* there are no cost limits -- nothing to do */ - if (cost_total <= 0) - return; /* ! * Adjust cost limit of each active worker to balance the total of cost ! * limit to autovacuum_vacuum_cost_limit. */ - cost_avail = (double) vac_cost_limit / vac_cost_delay; dlist_foreach(iter, &AutoVacuumShmem->av_runningWorkers) { WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur); if (worker->wi_proc != NULL && ! worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0) { - int limit = (int) - (cost_avail * worker->wi_cost_limit_base / cost_total); - /* * We put a lower bound of 1 on the cost_limit, to avoid division- ! * by-zero in the vacuum code. Also, in case of roundoff trouble ! * in these calculations, let's be sure we don't ever set ! * cost_limit to more than the base value. */ ! worker->wi_cost_limit = Max(Min(limit, ! worker->wi_cost_limit_base), ! 1); ! elog(DEBUG2, "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_limit_base=%d, cost_delay=%d)", worker->wi_proc->pid, worker->wi_dboid, worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_limit_base, ! worker->wi_cost_delay); } } } --- 1761,1808 ---- * The idea here is that we ration out I/O equally. The amount of I/O * that a worker can consume is determined by cost_limit/cost_delay, so we * try to equalize those ratios rather than the raw limit settings. */ ! int num_runningWorkers = 0; dlist_iter iter; dlist_foreach(iter, &AutoVacuumShmem->av_runningWorkers) { WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur); if (worker->wi_proc != NULL && ! worker->wi_cost_limit_base > 0 && worker->wi_cost_delay_base > 0) ! num_runningWorkers++; } /* ! * Adjust cost limit and cost delay of each active worker to balance the ! * total of cost_limit/cost_delay based on number of active workers. */ dlist_foreach(iter, &AutoVacuumShmem->av_runningWorkers) { WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur); if (worker->wi_proc != NULL && ! worker->wi_cost_limit_base > 0 && worker->wi_cost_delay_base > 0) { /* * We put a lower bound of 1 on the cost_limit, to avoid division- ! * by-zero in the vacuum code. ! */ ! worker->wi_cost_limit = Max((worker->wi_cost_limit_base / num_runningWorkers), ! 1); ! ! /* ! * We put a lower bound of 10ms on the cost_delay as some platforms have ! * this as sleep granularity. */ ! worker->wi_cost_delay = Max((worker->wi_cost_delay_base / num_runningWorkers), ! 10); ! elog(DEBUG2, "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_limit_base=%d, cost_delay=%d, cost_delay_base=%d)", worker->wi_proc->pid, worker->wi_dboid, worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_limit_base, ! worker->wi_cost_delay, worker->wi_cost_delay_base); } } } *************** *** 2285,2290 **** do_autovacuum(void) --- 2268,2274 ---- /* advertise my cost delay parameters for the balancing algorithm */ MyWorkerInfo->wi_cost_delay = tab->at_vacuum_cost_delay; + MyWorkerInfo->wi_cost_delay_base = tab->at_vacuum_cost_delay; MyWorkerInfo->wi_cost_limit = tab->at_vacuum_cost_limit; MyWorkerInfo->wi_cost_limit_base = tab->at_vacuum_cost_limit;