svn commit: r304577 - user/alc/PQ_LAUNDRY/sys/vm
Mark Johnston
markj at FreeBSD.org
Mon Aug 22 01:41:05 UTC 2016
Author: markj
Date: Mon Aug 22 01:41:03 2016
New Revision: 304577
URL: https://svnweb.freebsd.org/changeset/base/304577
Log:
Rework the background laundering target after r304442.
Now that we launder less frequently and at a rate proportional to the
ratio of dirty to clean inactive pages, we want to process more pages during
each background laundering run. Launder a constant number of pages,
derived from the amount of system memory. Cap the rate at which pages are
laundered to 4MB/s and add a check to ensure we don't launder too much on
larger-memory systems if page daemon wakeups are infrequent and the number
of dirty pages is large.
Discussed with: alc
Modified:
user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c
Modified: user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c
==============================================================================
--- user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c Mon Aug 22 01:28:02 2016 (r304576)
+++ user/alc/PQ_LAUNDRY/sys/vm/vm_pageout.c Mon Aug 22 01:41:03 2016 (r304577)
@@ -231,10 +231,15 @@ SYSCTL_INT(_vm, OID_AUTO, act_scan_laund
CTLFLAG_RW, &act_scan_laundry_weight, 0,
"weight given to clean vs. dirty pages in active queue scans");
-static u_int bkgrd_launder_max = 2048;
+static u_int bkgrd_launder_rate = 4096;
+SYSCTL_UINT(_vm, OID_AUTO, bkgrd_launder_rate,
+ CTLFLAG_RW, &bkgrd_launder_rate, 0,
+ "background laundering rate, in kilobytes per second");
+
+static u_int bkgrd_launder_max = 20 * 1024;
SYSCTL_UINT(_vm, OID_AUTO, bkgrd_launder_max,
CTLFLAG_RW, &bkgrd_launder_max, 0,
- "maximum background laundering rate, in pages per second");
+ "background laundering cap in kilobytes");
#define VM_PAGEOUT_PAGE_COUNT 16
int vm_pageout_page_count = VM_PAGEOUT_PAGE_COUNT;
@@ -1095,9 +1100,10 @@ static void
vm_pageout_laundry_worker(void *arg)
{
struct vm_domain *domain;
- uint64_t nclean, nlaundry;
+ uint64_t nclean, ndirty;
u_int last_launder, wakeups;
- int cycle, domidx, launder, prev_shortfall, shortfall, target;
+ int cycle, domidx, launder, prev_shortfall, shortfall;
+ int starting_target, target;
domidx = (uintptr_t)arg;
domain = &vm_dom[domidx];
@@ -1166,50 +1172,40 @@ vm_pageout_laundry_worker(void *arg)
*
* The background laundering threshold is not a constant.
* Instead, it is a slowly growing function of the number of
- * page daemon wakeups since the last laundering.
+ * page daemon wakeups since the last laundering. Thus, as the
+ * ratio of dirty to clean inactive pages grows, the amount of
+ * memory pressure required to trigger laundering decreases.
*/
nclean = vm_cnt.v_inactive_count + vm_cnt.v_free_count;
- nlaundry = vm_cnt.v_laundry_count;
+ ndirty = vm_cnt.v_laundry_count;
if (target == 0 && wakeups != last_launder &&
- nlaundry * isqrt(wakeups - last_launder) >= nclean) {
+ ndirty * isqrt(wakeups - last_launder) >= nclean) {
last_launder = wakeups;
-
- /*
- * The pagedaemon has woken up at least once since the
- * last background laundering run and we're above the
- * dirty page threshold. Launder some pages to balance
- * the inactive and laundry queues. We attempt to
- * finish within one second.
- */
- cycle = VM_LAUNDER_INTERVAL;
-
- /*
- * Set our target to that of the pagedaemon, scaled by
- * the relative lengths of the inactive and laundry
- * queues. Divide by a fudge factor as well: we don't
- * want to reclaim dirty pages at the same rate as clean
- * pages.
- */
- target = vm_cnt.v_free_target -
- vm_pageout_wakeup_thresh;
- /* Avoid division by zero. */
- if (nclean == 0)
- nclean = 1;
- target = nlaundry * (u_int)target / nclean / 10;
- if (target == 0)
- target = 1;
-
- /*
- * Make sure we don't exceed the background laundering
- * threshold.
- */
- target = min(target, bkgrd_launder_max);
+ target = starting_target =
+ (vm_cnt.v_free_target - vm_cnt.v_free_min) / 10;
}
+ /*
+ * We have a non-zero background laundering target. If we've
+ * laundered up to our maximum without observing a page daemon
+ * wakeup, just stop. This is a safety belt that ensures we
+ * don't launder an excessive amount if memory pressure is low
+ * and the ratio of dirty to clean pages is large. Otherwise,
+ * proceed at the background laundering rate.
+ */
if (target > 0) {
- if (cycle != 0)
- launder = target / cycle--;
- else
- target = 0;
+ if (last_launder == wakeups) {
+ if (starting_target - target >=
+ bkgrd_launder_max * PAGE_SIZE / 1024)
+ target = 0;
+ } else {
+ last_launder = wakeups;
+ starting_target = target;
+ }
+
+ launder = bkgrd_launder_rate * PAGE_SIZE / 1024 /
+ VM_LAUNDER_INTERVAL;
+ if (launder < target)
+ launder = target;
}
dolaundry:
@@ -1601,6 +1597,10 @@ drop_page:
if (page_shortage <= 0)
vm_page_deactivate(m);
else {
+ if (m->dirty == 0 &&
+ m->object->ref_count != 0 &&
+ pmap_is_modified(m))
+ vm_cnt.v_postponed_launderings++;
if (m->dirty == 0) {
vm_page_deactivate(m);
page_shortage -=
More information about the svn-src-user
mailing list