Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Buffer cache fixes to avoid thrashing between high and l...



details:   https://anonhg.NetBSD.org/src/rev/b3d6e546f11b
branches:  trunk
changeset: 558175:b3d6e546f11b
user:      tls <tls%NetBSD.org@localhost>
date:      Fri Jan 30 11:32:16 2004 +0000

description:
Buffer cache fixes to avoid thrashing between high and low water marks
and uncontrolled growth.

The key fix is from Dan Carasone, who noticed that buf_canfree() was
counting in _bytes_ but freeing in _buffers_, which caused the instant
drop to lowater observed by some users.

We now control the rate of growth; the probability of getting a new
allocation is inversely proportional to the current size of the
cache.  This idea is from a long-ago conversation with Kirk McKusick
and, if memory serves, was used for the file-system cache in some
other BSD variant at some point in history.

With growth and shrinkage more or less dealt with, we return the
default maximum cache size to 15%.  The default _minimum_ cache size
is raised from 1/16 of the maximum cache size to 1/8, since 1/16 was
chosen when the maximum size was 30% of memory.

Finally, after observing the behaviour of the pagedaemon and the
buffer cache drainer under pathological workloads (e.g. a benchmark
that steps through 75% of available memory backwards) I have moved
the call to buf_drain() to the beginning of the pagedaemon from the
end; if the pagedaemon bogs down, it still won't get run as often
as it should, but at least this way it will see the state of the
free count and free target _before_ the scan step does its thing.

diffstat:

 sys/kern/vfs_bio.c    |  40 +++++++++++++++++++++++++++++-----------
 sys/uvm/uvm_pdaemon.c |  12 +++++++++---
 2 files changed, 38 insertions(+), 14 deletions(-)

diffs (137 lines):

diff -r a649a0ea2f64 -r b3d6e546f11b sys/kern/vfs_bio.c
--- a/sys/kern/vfs_bio.c        Fri Jan 30 09:42:01 2004 +0000
+++ b/sys/kern/vfs_bio.c        Fri Jan 30 11:32:16 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_bio.c,v 1.113 2004/01/27 11:35:23 dan Exp $        */
+/*     $NetBSD: vfs_bio.c,v 1.114 2004/01/30 11:32:16 tls Exp $        */
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -81,7 +81,7 @@
 #include "opt_softdep.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.113 2004/01/27 11:35:23 dan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.114 2004/01/30 11:32:16 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -108,7 +108,7 @@
 #  error BUFCACHE is not between 5 and 95
 # endif
 #else
-# define BUFCACHE 10
+# define BUFCACHE 15
 #endif
 
 u_int  nbuf;                   /* XXX - for softdep_lockedbufs */
@@ -338,8 +338,8 @@
         */
        bufmem = 0;
        bufmem_hiwater = buf_memcalc();
-       /* lowater is approx. 2% of memory (with bufcache=30) */
-       bufmem_lowater = (bufmem_hiwater >> 4);
+       /* lowater is approx. 2% of memory (with bufcache=15) */
+       bufmem_lowater = (bufmem_hiwater >> 3);
        if (bufmem_lowater < 64 * 1024)
                /* Ensure a reasonable minimum value */
                bufmem_lowater = 64 * 1024;
@@ -393,8 +393,21 @@
 static int
 buf_lotsfree(void)
 {
-       return (bufmem < bufmem_lowater ||
-               (bufmem < bufmem_hiwater && uvmexp.free > 2*uvmexp.freetarg));
+       int try, thresh;
+
+       if (bufmem < bufmem_lowater) {
+               return 1;
+       }
+
+       try = random() & 0x0000000fL;
+
+       thresh = (16 * bufmem) / bufmem_hiwater;
+
+       if ((try > thresh) && (uvmexp.free > ( 2 * uvmexp.freetarg))) {
+               return 1;
+       }
+
+       return 0;
 }
 
 /*
@@ -411,8 +424,8 @@
 
        n = uvmexp.freetarg - uvmexp.free;
        if (n < 0)
-               n = 0;
-       return 2*n;
+               return 0;
+       return 2 * n;
 }
 
 /*
@@ -1223,8 +1236,9 @@
 
        s = splbio();
        simple_lock(&bqueue_slock);
-       while (n-- > 0 && bufmem > bufmem_lowater)
+       while (size < n && bufmem > bufmem_lowater)
                size += buf_trim();
+
        simple_unlock(&bqueue_slock);
        splx(s);
        return size;
@@ -1470,7 +1484,11 @@
                        return (EINVAL);
                bufcache = t;
                bufmem_hiwater = buf_memcalc();
-               bufmem_lowater = (bufmem_hiwater >> 4);
+               bufmem_lowater = (bufmem_hiwater >> 3);
+               if (bufmem_lowater < 64 * 1024) 
+                       /* Ensure a reasonable minimum value */
+                       bufmem_lowater = 64 * 1024;
+
        } else if (rnode->sysctl_num == sysctlnum_bufmemlowater) {
                bufmem_lowater = t;
        } else if (rnode->sysctl_num == sysctlnum_bufmemhiwater) {
diff -r a649a0ea2f64 -r b3d6e546f11b sys/uvm/uvm_pdaemon.c
--- a/sys/uvm/uvm_pdaemon.c     Fri Jan 30 09:42:01 2004 +0000
+++ b/sys/uvm/uvm_pdaemon.c     Fri Jan 30 11:32:16 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_pdaemon.c,v 1.57 2004/01/04 11:33:32 jdolecek Exp $        */
+/*     $NetBSD: uvm_pdaemon.c,v 1.58 2004/01/30 11:32:16 tls Exp $     */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pdaemon.c,v 1.57 2004/01/04 11:33:32 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pdaemon.c,v 1.58 2004/01/30 11:32:16 tls Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -226,6 +226,13 @@
                UVMHIST_LOG(pdhist,"  <<WOKE UP>>",0,0,0,0);
 
                /*
+                * The metadata cache drainer knows about uvmexp.free
+                * and uvmexp.freetarg.  We call it _before_ scanning
+                * so that it sees the amount we really want.
+                */
+               buf_drain(0);
+
+               /*
                 * now lock page queues and recompute inactive count
                 */
 
@@ -273,7 +280,6 @@
                 * drain pool resources now that we're not holding any locks
                 */
 
-               buf_drain(0);
                pool_drain(0);
 
                /*



Home | Main Index | Thread Index | Old Index