@@ -190,7 +190,7 @@ typedef struct autovac_table
190
190
*
191
191
* wi_links entry into free list or running list
192
192
* wi_dboid OID of the database this worker is supposed to work on
193
- * wi_tableoid OID of the table currently being vacuumed
193
+ * wi_tableoid OID of the table currently being vacuumed, if any
194
194
* wi_proc pointer to PGPROC of the running worker, NULL if not started
195
195
* wi_launchtime Time at which this worker was launched
196
196
* wi_cost_* Vacuum cost-based delay parameters current in this worker
@@ -1629,7 +1629,7 @@ FreeWorkerInfo(int code, Datum arg)
1629
1629
* limit setting of the remaining workers.
1630
1630
*
1631
1631
* We somewhat ignore the risk that the launcher changes its PID
1632
- * between we reading it and the actual kill; we expect ProcKill to be
1632
+ * between us reading it and the actual kill; we expect ProcKill to be
1633
1633
* called shortly after us, and we assume that PIDs are not reused too
1634
1634
* quickly after a process exits.
1635
1635
*/
@@ -1673,16 +1673,18 @@ AutoVacuumUpdateDelay(void)
1673
1673
1674
1674
/*
1675
1675
* autovac_balance_cost
1676
- * Recalculate the cost limit setting for each active workers .
1676
+ * Recalculate the cost limit setting for each active worker .
1677
1677
*
1678
1678
* Caller must hold the AutovacuumLock in exclusive mode.
1679
1679
*/
1680
1680
static void
1681
1681
autovac_balance_cost (void )
1682
1682
{
1683
- WorkerInfo worker ;
1684
-
1685
1683
/*
1684
+ * The idea here is that we ration out I/O equally. The amount of I/O
1685
+ * that a worker can consume is determined by cost_limit/cost_delay, so
1686
+ * we try to equalize those ratios rather than the raw limit settings.
1687
+ *
1686
1688
* note: in cost_limit, zero also means use value from elsewhere, because
1687
1689
* zero is not a valid value.
1688
1690
*/
@@ -1692,6 +1694,7 @@ autovac_balance_cost(void)
1692
1694
autovacuum_vac_cost_delay : VacuumCostDelay );
1693
1695
double cost_total ;
1694
1696
double cost_avail ;
1697
+ WorkerInfo worker ;
1695
1698
1696
1699
/* not set? nothing to do */
1697
1700
if (vac_cost_limit <= 0 || vac_cost_delay <= 0 )
@@ -1718,7 +1721,7 @@ autovac_balance_cost(void)
1718
1721
return ;
1719
1722
1720
1723
/*
1721
- * Adjust each cost limit of active workers to balance the total of cost
1724
+ * Adjust cost limit of each active worker to balance the total of cost
1722
1725
* limit to autovacuum_vacuum_cost_limit.
1723
1726
*/
1724
1727
cost_avail = (double ) vac_cost_limit / vac_cost_delay ;
@@ -1734,14 +1737,19 @@ autovac_balance_cost(void)
1734
1737
(cost_avail * worker -> wi_cost_limit_base / cost_total );
1735
1738
1736
1739
/*
1737
- * We put a lower bound of 1 to the cost_limit, to avoid division-
1738
- * by-zero in the vacuum code.
1740
+ * We put a lower bound of 1 on the cost_limit, to avoid division-
1741
+ * by-zero in the vacuum code. Also, in case of roundoff trouble
1742
+ * in these calculations, let's be sure we don't ever set
1743
+ * cost_limit to more than the base value.
1739
1744
*/
1740
- worker -> wi_cost_limit = Max (Min (limit , worker -> wi_cost_limit_base ), 1 );
1741
-
1742
- elog (DEBUG2 , "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_delay=%d)" ,
1743
- worker -> wi_proc -> pid , worker -> wi_dboid ,
1744
- worker -> wi_tableoid , worker -> wi_cost_limit , worker -> wi_cost_delay );
1745
+ worker -> wi_cost_limit = Max (Min (limit ,
1746
+ worker -> wi_cost_limit_base ),
1747
+ 1 );
1748
+
1749
+ elog (DEBUG2 , "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_limit_base=%d, cost_delay=%d)" ,
1750
+ worker -> wi_proc -> pid , worker -> wi_dboid , worker -> wi_tableoid ,
1751
+ worker -> wi_cost_limit , worker -> wi_cost_limit_base ,
1752
+ worker -> wi_cost_delay );
1745
1753
}
1746
1754
1747
1755
worker = (WorkerInfo ) SHMQueueNext (& AutoVacuumShmem -> av_runningWorkers ,
@@ -2125,6 +2133,8 @@ do_autovacuum(void)
2125
2133
autovac_table * tab ;
2126
2134
WorkerInfo worker ;
2127
2135
bool skipit ;
2136
+ int stdVacuumCostDelay ;
2137
+ int stdVacuumCostLimit ;
2128
2138
2129
2139
CHECK_FOR_INTERRUPTS ();
2130
2140
@@ -2198,11 +2208,15 @@ do_autovacuum(void)
2198
2208
MyWorkerInfo -> wi_tableoid = relid ;
2199
2209
LWLockRelease (AutovacuumScheduleLock );
2200
2210
2201
- /* Set the initial vacuum cost parameters for this table */
2202
- VacuumCostDelay = tab -> at_vacuum_cost_delay ;
2203
- VacuumCostLimit = tab -> at_vacuum_cost_limit ;
2211
+ /*
2212
+ * Remember the prevailing values of the vacuum cost GUCs. We have
2213
+ * to restore these at the bottom of the loop, else we'll compute
2214
+ * wrong values in the next iteration of autovac_balance_cost().
2215
+ */
2216
+ stdVacuumCostDelay = VacuumCostDelay ;
2217
+ stdVacuumCostLimit = VacuumCostLimit ;
2204
2218
2205
- /* Last fixups before actually starting to work */
2219
+ /* Must hold AutovacuumLock while mucking with cost balance info */
2206
2220
LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
2207
2221
2208
2222
/* advertise my cost delay parameters for the balancing algorithm */
@@ -2213,6 +2227,9 @@ do_autovacuum(void)
2213
2227
/* do a balance */
2214
2228
autovac_balance_cost ();
2215
2229
2230
+ /* set the active cost parameters from the result of that */
2231
+ AutoVacuumUpdateDelay ();
2232
+
2216
2233
/* done */
2217
2234
LWLockRelease (AutovacuumLock );
2218
2235
@@ -2290,10 +2307,20 @@ do_autovacuum(void)
2290
2307
pfree (tab -> at_relname );
2291
2308
pfree (tab );
2292
2309
2293
- /* remove my info from shared memory */
2310
+ /*
2311
+ * Remove my info from shared memory. We could, but intentionally
2312
+ * don't, clear wi_cost_limit and friends --- this is on the
2313
+ * assumption that we probably have more to do with similar cost
2314
+ * settings, so we don't want to give up our share of I/O for a very
2315
+ * short interval and thereby thrash the global balance.
2316
+ */
2294
2317
LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
2295
2318
MyWorkerInfo -> wi_tableoid = InvalidOid ;
2296
2319
LWLockRelease (AutovacuumLock );
2320
+
2321
+ /* restore vacuum cost GUCs for the next iteration */
2322
+ VacuumCostDelay = stdVacuumCostDelay ;
2323
+ VacuumCostLimit = stdVacuumCostLimit ;
2297
2324
}
2298
2325
2299
2326
/*
0 commit comments