svn commit: r331732 - head/sys/vm

Mark Johnston markj at FreeBSD.org
Thu Mar 29 14:27:41 UTC 2018


Author: markj
Date: Thu Mar 29 14:27:40 2018
New Revision: 331732
URL: https://svnweb.freebsd.org/changeset/base/331732

Log:
  Fix the background laundering mechanism after r329882.
  
  Rather than using the number of inactive queue scans as a metric for
  how many clean pages are being freed by the page daemon, have the
  page daemon keep a running counter of the number of pages it has freed,
  and have the laundry thread use that when computing the background
  laundering threshold.
  
  Reviewed by:	kib
  Differential Revision:	https://reviews.freebsd.org/D14884

Modified:
  head/sys/vm/vm_pageout.c
  head/sys/vm/vm_pagequeue.h

Modified: head/sys/vm/vm_pageout.c
==============================================================================
--- head/sys/vm/vm_pageout.c	Thu Mar 29 13:55:23 2018	(r331731)
+++ head/sys/vm/vm_pageout.c	Thu Mar 29 14:27:40 2018	(r331732)
@@ -943,8 +943,7 @@ vm_pageout_laundry_worker(void *arg)
 {
 	struct vm_domain *vmd;
 	struct vm_pagequeue *pq;
-	uint64_t nclean, ndirty;
-	u_int inactq_scans, last_launder;
+	uint64_t nclean, ndirty, nfreed;
 	int domain, last_target, launder, shortfall, shortfall_cycle, target;
 	bool in_shortfall;
 
@@ -958,8 +957,7 @@ vm_pageout_laundry_worker(void *arg)
 	in_shortfall = false;
 	shortfall_cycle = 0;
 	target = 0;
-	inactq_scans = 0;
-	last_launder = 0;
+	nfreed = 0;
 
 	/*
 	 * Calls to these handlers are serialized by the swap syscall lock.
@@ -1000,7 +998,6 @@ vm_pageout_laundry_worker(void *arg)
 			target = 0;
 			goto trybackground;
 		}
-		last_launder = inactq_scans;
 		launder = target / shortfall_cycle--;
 		goto dolaundry;
 
@@ -1009,24 +1006,23 @@ vm_pageout_laundry_worker(void *arg)
 		 * meet the conditions to perform background laundering:
 		 *
 		 * 1. The ratio of dirty to clean inactive pages exceeds the
-		 *    background laundering threshold and the pagedaemon has
-		 *    been woken up to reclaim pages since our last
-		 *    laundering, or
+		 *    background laundering threshold, or
 		 * 2. we haven't yet reached the target of the current
 		 *    background laundering run.
 		 *
 		 * The background laundering threshold is not a constant.
 		 * Instead, it is a slowly growing function of the number of
-		 * page daemon scans 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.
+		 * clean pages freed by the page daemon since the last
+		 * background laundering.  Thus, as the ratio of dirty to
+		 * clean inactive pages grows, the amount of memory pressure
+		 * required to trigger laundering decreases.
 		 */
 trybackground:
 		nclean = vmd->vmd_free_count +
 		    vmd->vmd_pagequeues[PQ_INACTIVE].pq_cnt;
 		ndirty = vmd->vmd_pagequeues[PQ_LAUNDRY].pq_cnt;
-		if (target == 0 && inactq_scans != last_launder &&
-		    ndirty * isqrt(inactq_scans - last_launder) >= nclean) {
+		if (target == 0 && ndirty * isqrt(nfreed /
+		    (vmd->vmd_free_target - vmd->vmd_free_min)) >= nclean) {
 			target = vmd->vmd_background_launder_target;
 		}
 
@@ -1039,8 +1035,8 @@ trybackground:
 		 * proceed at the background laundering rate.
 		 */
 		if (target > 0) {
-			if (inactq_scans != last_launder) {
-				last_launder = inactq_scans;
+			if (nfreed > 0) {
+				nfreed = 0;
 				last_target = target;
 			} else if (last_target - target >=
 			    vm_background_launder_max * PAGE_SIZE / 1024) {
@@ -1089,7 +1085,8 @@ dolaundry:
 
 		if (target == 0)
 			vmd->vmd_laundry_request = VM_LAUNDRY_IDLE;
-		inactq_scans = vmd->vmd_inactq_scans;
+		nfreed += vmd->vmd_clean_pages_freed;
+		vmd->vmd_clean_pages_freed = 0;
 		vm_pagequeue_unlock(pq);
 	}
 }
@@ -1367,7 +1364,8 @@ drop_page:
 				    VM_LAUNDRY_BACKGROUND;
 			wakeup(&vmd->vmd_laundry_request);
 		}
-		vmd->vmd_inactq_scans++;
+		vmd->vmd_clean_pages_freed +=
+		    starting_page_shortage - page_shortage;
 		vm_pagequeue_unlock(pq);
 	}
 

Modified: head/sys/vm/vm_pagequeue.h
==============================================================================
--- head/sys/vm/vm_pagequeue.h	Thu Mar 29 13:55:23 2018	(r331731)
+++ head/sys/vm/vm_pagequeue.h	Thu Mar 29 14:27:40 2018	(r331732)
@@ -86,6 +86,7 @@ struct sysctl_oid;
  * d   vm_domainset_lock
  * a   atomic
  * c   const after boot
+ * q   page queue lock
 */
 struct vm_domain {
 	struct vm_pagequeue vmd_pagequeues[PQ_COUNT];
@@ -112,15 +113,15 @@ struct vm_domain {
 	int vmd_pageout_pages_needed;	/* (d) page daemon waiting for pages? */
 	bool vmd_minset;		/* (d) Are we in vm_min_domains? */
 	bool vmd_severeset;		/* (d) Are we in vm_severe_domains? */
-	int vmd_inactq_scans;
 	enum {
 		VM_LAUNDRY_IDLE = 0,
 		VM_LAUNDRY_BACKGROUND,
 		VM_LAUNDRY_SHORTFALL
 	} vmd_laundry_request;
 
-	/* Paging thresholds. */
-	u_int vmd_background_launder_target;
+	/* Paging thresholds and targets. */
+	u_int vmd_clean_pages_freed;	/* (q) accumulator for laundry thread */
+	u_int vmd_background_launder_target; /* (c) */
 	u_int vmd_free_reserved;	/* (c) pages reserved for deadlock */
 	u_int vmd_free_target;		/* (c) pages desired free */
 	u_int vmd_free_min;		/* (c) pages desired free */


More information about the svn-src-head mailing list