Author: markj
Date: Mon Dec 11 15:33:24 2017
New Revision: 326770
URL: https://svnweb.freebsd.org/changeset/base/326770

Log:
  Use a dedicated counter for inactive queue scans.
  
  The laundry thread keeps track of the number of inactive queue scans
  performed by the page daemon, and was previously using the v_pdwakeups
  counter to count them. However, in some cases the inactive queue may
  be scanned multiple times after a single wakeup, so it's more accurate
  to use a dedicated counter.
  
  Reviewed by:  alc, kib (previous version)
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D13422

Modified:
  head/sys/vm/vm_pageout.c

Modified: head/sys/vm/vm_pageout.c
==============================================================================
--- head/sys/vm/vm_pageout.c    Mon Dec 11 14:54:42 2017        (r326769)
+++ head/sys/vm/vm_pageout.c    Mon Dec 11 15:33:24 2017        (r326770)
@@ -159,6 +159,7 @@ static enum {
        VM_LAUNDRY_BACKGROUND,
        VM_LAUNDRY_SHORTFALL
 } vm_laundry_request = VM_LAUNDRY_IDLE;
+static int vm_inactq_scans;
 
 static int vm_pageout_update_period;
 static int disable_swap_pageouts;
@@ -961,7 +962,7 @@ vm_pageout_laundry_worker(void *arg)
        struct vm_domain *domain;
        struct vm_pagequeue *pq;
        uint64_t nclean, ndirty;
-       u_int last_launder, wakeups;
+       u_int inactq_scans, last_launder;
        int domidx, last_target, launder, shortfall, shortfall_cycle, target;
        bool in_shortfall;
 
@@ -975,6 +976,7 @@ vm_pageout_laundry_worker(void *arg)
        in_shortfall = false;
        shortfall_cycle = 0;
        target = 0;
+       inactq_scans = 0;
        last_launder = 0;
 
        /*
@@ -993,7 +995,6 @@ vm_pageout_laundry_worker(void *arg)
                KASSERT(shortfall_cycle >= 0,
                    ("negative cycle %d", shortfall_cycle));
                launder = 0;
-               wakeups = VM_CNT_FETCH(v_pdwakeups);
 
                /*
                 * First determine whether we need to launder pages to meet a
@@ -1017,7 +1018,7 @@ vm_pageout_laundry_worker(void *arg)
                        target = 0;
                        goto trybackground;
                }
-               last_launder = wakeups;
+               last_launder = inactq_scans;
                launder = target / shortfall_cycle--;
                goto dolaundry;
 
@@ -1034,29 +1035,29 @@ 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.  Thus, as the
+                * 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.
                 */
 trybackground:
                nclean = vm_cnt.v_inactive_count + vm_cnt.v_free_count;
                ndirty = vm_cnt.v_laundry_count;
-               if (target == 0 && wakeups != last_launder &&
-                   ndirty * isqrt(wakeups - last_launder) >= nclean) {
+               if (target == 0 && inactq_scans != last_launder &&
+                   ndirty * isqrt(inactq_scans - last_launder) >= nclean) {
                        target = vm_background_launder_target;
                }
 
                /*
                 * 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
+                * request, 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 (wakeups != last_launder) {
-                               last_launder = wakeups;
+                       if (inactq_scans != last_launder) {
+                               last_launder = inactq_scans;
                                last_target = target;
                        } else if (last_target - target >=
                            vm_background_launder_max * PAGE_SIZE / 1024) {
@@ -1104,6 +1105,7 @@ dolaundry:
 
                if (target == 0)
                        vm_laundry_request = VM_LAUNDRY_IDLE;
+               inactq_scans = vm_inactq_scans;
                vm_pagequeue_unlock(pq);
        }
 }
@@ -1349,12 +1351,16 @@ drop_page:
         * need to launder more aggressively.  If PQ_LAUNDRY is empty and no
         * swap devices are configured, the laundry thread has no work to do, so
         * don't bother waking it up.
+        *
+        * The laundry thread uses the number of inactive queue scans elapsed
+        * since the last laundering to determine whether to launder again, so
+        * keep count.
         */
-       if (vm_laundry_request == VM_LAUNDRY_IDLE &&
-           starting_page_shortage > 0) {
+       if (starting_page_shortage > 0) {
                pq = &vm_dom[0].vmd_pagequeues[PQ_LAUNDRY];
                vm_pagequeue_lock(pq);
-               if (pq->pq_cnt > 0 || atomic_load_acq_int(&swapdev_enabled)) {
+               if (vm_laundry_request == VM_LAUNDRY_IDLE &&
+                   (pq->pq_cnt > 0 || atomic_load_acq_int(&swapdev_enabled))) {
                        if (page_shortage > 0) {
                                vm_laundry_request = VM_LAUNDRY_SHORTFALL;
                                VM_CNT_INC(v_pdshortfalls);
@@ -1362,6 +1368,7 @@ drop_page:
                                vm_laundry_request = VM_LAUNDRY_BACKGROUND;
                        wakeup(&vm_laundry_request);
                }
+               vm_inactq_scans++;
                vm_pagequeue_unlock(pq);
        }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to