@@ -184,7 +184,7 @@ typedef struct autovac_table
184
184
*
185
185
* wi_links entry into free list or running list
186
186
* wi_dboid OID of the database this worker is supposed to work on
187
- * wi_tableoid OID of the table currently being vacuumed
187
+ * wi_tableoid OID of the table currently being vacuumed, if any
188
188
* wi_proc pointer to PGPROC of the running worker, NULL if not started
189
189
* wi_launchtime Time at which this worker was launched
190
190
* wi_cost_* Vacuum cost-based delay parameters current in this worker
@@ -1651,7 +1651,7 @@ FreeWorkerInfo(int code, Datum arg)
1651
1651
* limit setting of the remaining workers.
1652
1652
*
1653
1653
* We somewhat ignore the risk that the launcher changes its PID
1654
- * between we reading it and the actual kill; we expect ProcKill to be
1654
+ * between us reading it and the actual kill; we expect ProcKill to be
1655
1655
* called shortly after us, and we assume that PIDs are not reused too
1656
1656
* quickly after a process exits.
1657
1657
*/
@@ -1695,16 +1695,18 @@ AutoVacuumUpdateDelay(void)
1695
1695
1696
1696
/*
1697
1697
* autovac_balance_cost
1698
- * Recalculate the cost limit setting for each active workers .
1698
+ * Recalculate the cost limit setting for each active worker .
1699
1699
*
1700
1700
* Caller must hold the AutovacuumLock in exclusive mode.
1701
1701
*/
1702
1702
static void
1703
1703
autovac_balance_cost (void )
1704
1704
{
1705
- WorkerInfo worker ;
1706
-
1707
1705
/*
1706
+ * The idea here is that we ration out I/O equally. The amount of I/O
1707
+ * that a worker can consume is determined by cost_limit/cost_delay, so
1708
+ * we try to equalize those ratios rather than the raw limit settings.
1709
+ *
1708
1710
* note: in cost_limit, zero also means use value from elsewhere, because
1709
1711
* zero is not a valid value.
1710
1712
*/
@@ -1714,6 +1716,7 @@ autovac_balance_cost(void)
1714
1716
autovacuum_vac_cost_delay : VacuumCostDelay );
1715
1717
double cost_total ;
1716
1718
double cost_avail ;
1719
+ WorkerInfo worker ;
1717
1720
1718
1721
/* not set? nothing to do */
1719
1722
if (vac_cost_limit <= 0 || vac_cost_delay <= 0 )
@@ -1740,7 +1743,7 @@ autovac_balance_cost(void)
1740
1743
return ;
1741
1744
1742
1745
/*
1743
- * Adjust each cost limit of active workers to balance the total of cost
1746
+ * Adjust cost limit of each active worker to balance the total of cost
1744
1747
* limit to autovacuum_vacuum_cost_limit.
1745
1748
*/
1746
1749
cost_avail = (double ) vac_cost_limit / vac_cost_delay ;
@@ -1756,14 +1759,19 @@ autovac_balance_cost(void)
1756
1759
(cost_avail * worker -> wi_cost_limit_base / cost_total );
1757
1760
1758
1761
/*
1759
- * We put a lower bound of 1 to the cost_limit, to avoid division-
1760
- * by-zero in the vacuum code.
1762
+ * We put a lower bound of 1 on the cost_limit, to avoid division-
1763
+ * by-zero in the vacuum code. Also, in case of roundoff trouble
1764
+ * in these calculations, let's be sure we don't ever set
1765
+ * cost_limit to more than the base value.
1761
1766
*/
1762
- worker -> wi_cost_limit = Max (Min (limit , worker -> wi_cost_limit_base ), 1 );
1763
-
1764
- elog (DEBUG2 , "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_delay=%d)" ,
1765
- worker -> wi_proc -> pid , worker -> wi_dboid ,
1766
- worker -> wi_tableoid , worker -> wi_cost_limit , worker -> wi_cost_delay );
1767
+ worker -> wi_cost_limit = Max (Min (limit ,
1768
+ worker -> wi_cost_limit_base ),
1769
+ 1 );
1770
+
1771
+ elog (DEBUG2 , "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_limit_base=%d, cost_delay=%d)" ,
1772
+ worker -> wi_proc -> pid , worker -> wi_dboid , worker -> wi_tableoid ,
1773
+ worker -> wi_cost_limit , worker -> wi_cost_limit_base ,
1774
+ worker -> wi_cost_delay );
1767
1775
}
1768
1776
1769
1777
worker = (WorkerInfo ) SHMQueueNext (& AutoVacuumShmem -> av_runningWorkers ,
@@ -2015,6 +2023,8 @@ do_autovacuum(void)
2015
2023
char * datname ,
2016
2024
* nspname ,
2017
2025
* relname ;
2026
+ int stdVacuumCostDelay ;
2027
+ int stdVacuumCostLimit ;
2018
2028
2019
2029
CHECK_FOR_INTERRUPTS ();
2020
2030
@@ -2086,11 +2096,15 @@ do_autovacuum(void)
2086
2096
MyWorkerInfo -> wi_tableoid = relid ;
2087
2097
LWLockRelease (AutovacuumScheduleLock );
2088
2098
2089
- /* Set the initial vacuum cost parameters for this table */
2090
- VacuumCostDelay = tab -> at_vacuum_cost_delay ;
2091
- VacuumCostLimit = tab -> at_vacuum_cost_limit ;
2099
+ /*
2100
+ * Remember the prevailing values of the vacuum cost GUCs. We have
2101
+ * to restore these at the bottom of the loop, else we'll compute
2102
+ * wrong values in the next iteration of autovac_balance_cost().
2103
+ */
2104
+ stdVacuumCostDelay = VacuumCostDelay ;
2105
+ stdVacuumCostLimit = VacuumCostLimit ;
2092
2106
2093
- /* Last fixups before actually starting to work */
2107
+ /* Must hold AutovacuumLock while mucking with cost balance info */
2094
2108
LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
2095
2109
2096
2110
/* advertise my cost delay parameters for the balancing algorithm */
@@ -2101,6 +2115,9 @@ do_autovacuum(void)
2101
2115
/* do a balance */
2102
2116
autovac_balance_cost ();
2103
2117
2118
+ /* set the active cost parameters from the result of that */
2119
+ AutoVacuumUpdateDelay ();
2120
+
2104
2121
/* done */
2105
2122
LWLockRelease (AutovacuumLock );
2106
2123
@@ -2182,10 +2199,20 @@ do_autovacuum(void)
2182
2199
if (relname )
2183
2200
pfree (relname );
2184
2201
2185
- /* remove my info from shared memory */
2202
+ /*
2203
+ * Remove my info from shared memory. We could, but intentionally
2204
+ * don't, clear wi_cost_limit and friends --- this is on the
2205
+ * assumption that we probably have more to do with similar cost
2206
+ * settings, so we don't want to give up our share of I/O for a very
2207
+ * short interval and thereby thrash the global balance.
2208
+ */
2186
2209
LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
2187
2210
MyWorkerInfo -> wi_tableoid = InvalidOid ;
2188
2211
LWLockRelease (AutovacuumLock );
2212
+
2213
+ /* restore vacuum cost GUCs for the next iteration */
2214
+ VacuumCostDelay = stdVacuumCostDelay ;
2215
+ VacuumCostLimit = stdVacuumCostLimit ;
2189
2216
}
2190
2217
2191
2218
/*
0 commit comments