diff options
author | silby <silby@FreeBSD.org> | 2002-02-27 18:03:02 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2002-02-27 18:03:02 +0000 |
commit | 230f96f3ce0496343800b107e3e952de9d7747de (patch) | |
tree | c901dac940b687287b5e926cf9d3fee071a8a002 /sys/alpha | |
parent | 62c8af563fb2047ffe16514abfeef77eea1691b8 (diff) | |
download | FreeBSD-src-230f96f3ce0496343800b107e3e952de9d7747de.zip FreeBSD-src-230f96f3ce0496343800b107e3e952de9d7747de.tar.gz |
Fix a horribly suboptimal algorithm in the vm_daemon.
In order to determine what to page out, the vm_daemon checks
reference bits on all pages belonging to all processes. Unfortunately,
the algorithm used reacted badly with shared pages; each shared page
would be checked once per process sharing it; this caused an O(N^2)
growth of tlb invalidations. The algorithm has been changed so that
each page will be checked only 16 times.
Prior to this change, a fork/sleepbomb of 1300 processes could cause
the vm_daemon to take over 60 seconds to complete, effectively
freezing the system for that time period. With this change
in place, the vm_daemon completes in less than a second. Any system
with hundreds of processes sharing pages should benefit from this change.
Note that the vm_daemon is only run when the system is under extreme
memory pressure. It is likely that many people with loaded systems saw
no symptoms of this problem until they reached the point where swapping
began.
Special thanks go to dillon, peter, and Chuck Cranor, who helped me
get up to speed with vm internals.
PR: 33542, 20393
Reviewed by: dillon
MFC after: 1 week
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/pmap.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c index e628d14..1bee3dd 100644 --- a/sys/alpha/alpha/pmap.c +++ b/sys/alpha/alpha/pmap.c @@ -2745,15 +2745,19 @@ pmap_pageable(pmap, sva, eva, pageable) } /* - * this routine returns true if a physical page resides - * in the given pmap. + * Returns true if the pmap's pv is one of the first + * 16 pvs linked to from this page. This count may + * be changed upwards or downwards in the future; it + * is only necessary that true be returned for a small + * subset of pmaps for proper page aging. */ boolean_t -pmap_page_exists(pmap, m) +pmap_page_exists_quick(pmap, m) pmap_t pmap; vm_page_t m; { - register pv_entry_t pv; + pv_entry_t pv; + int loops = 0; int s; if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) @@ -2769,6 +2773,9 @@ pmap_page_exists(pmap, m) splx(s); return TRUE; } + loops++; + if (loops >= 16) + break; } splx(s); return (FALSE); @@ -2932,7 +2939,14 @@ pmap_phys_address(ppn) /* * pmap_ts_referenced: * - * Return the count of reference bits for a page, clearing all of them. + * Return a count of reference bits for a page, clearing those bits. + * It is not necessary for every reference bit to be cleared, but it + * is necessary that 0 only be returned when there are truly no + * reference bits set. + * + * XXX: The exact number of bits to check and clear is a matter that + * should be tested and standardized at some point in the future for + * optimal aging of shared pages. */ int pmap_ts_referenced(vm_page_t m) |