Eviction strategy no longer chooses external pages when the total external page
count becomes low (4% of total). This primitive algorithm improves performance
considerably through retention of code pages which would otherwise be
continuously paged out and paged in.
---
vm/vm_page.c | 46 +++++++++++++++++++++++++---------------------
1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/vm/vm_page.c b/vm/vm_page.c
index ba3a52ff..1489fb7a 100644
--- a/vm/vm_page.c
+++ b/vm/vm_page.c
@@ -2021,9 +2021,8 @@ vm_page_balance(void)
}
static boolean_t
-vm_page_evict_once(boolean_t external, boolean_t alloc_paused)
+vm_page_evict_once(boolean_t alloc_paused)
{
- boolean_t evicted;
unsigned int i;
/*
@@ -2032,12 +2031,29 @@ vm_page_evict_once(boolean_t external, boolean_t
alloc_paused)
*/
for (i = vm_page_segs_size - 1; i < vm_page_segs_size; i--) {
- evicted = vm_page_seg_evict(vm_page_seg_get(i),
- external, alloc_paused);
+ struct vm_page_seg* seg = vm_page_seg_get(i);
+ unsigned long nr_ext_pages = (seg->active_pages.external.nr_pages +
+ seg->inactive_pages.external.nr_pages);
- if (evicted) {
- return TRUE;
- }
+ if (nr_ext_pages)
+ {
+ unsigned long nr_int_pages
+ = (seg->active_pages.internal.nr_pages +
+ seg->inactive_pages.internal.nr_pages);
+
+ /* Don't page out external pages if they total less than 1
+ in N pageable pages in this segment. This is an
+ extremely primitive starting position for an actual
+ eviction strategy. */
+ if ((nr_int_pages / nr_ext_pages) <= /*N*/ 25 &&
+ vm_page_seg_evict(seg, TRUE, alloc_paused))
+ return TRUE;
+ }
+ }
+
+ for (i = vm_page_segs_size - 1; i < vm_page_segs_size; i--) {
+ if (vm_page_seg_evict(vm_page_seg_get(i), FALSE, alloc_paused))
+ return TRUE;
}
return FALSE;
@@ -2049,18 +2065,16 @@ vm_page_evict_once(boolean_t external, boolean_t
alloc_paused)
boolean_t
vm_page_evict(boolean_t *should_wait)
{
- boolean_t pause, evicted, external, alloc_paused;
+ boolean_t pause, evicted, alloc_paused;
unsigned int i;
*should_wait = TRUE;
- external = TRUE;
simple_lock(&vm_page_queue_free_lock);
vm_page_external_laundry_count = 0;
alloc_paused = vm_page_alloc_paused;
simple_unlock(&vm_page_queue_free_lock);
-again:
vm_page_lock_queues();
pause = (vm_page_laundry_count >= VM_PAGE_MAX_LAUNDRY);
vm_page_unlock_queues();
@@ -2071,7 +2085,7 @@ again:
}
for (i = 0; i < VM_PAGE_MAX_EVICTIONS; i++) {
- evicted = vm_page_evict_once(external, alloc_paused);
+ evicted = vm_page_evict_once(alloc_paused);
if (!evicted) {
break;
@@ -2094,16 +2108,6 @@ again:
return FALSE;
}
- /*
- * Eviction failed, consider pages from internal objects on the
- * next attempt.
- */
- if (external && IP_VALID(memory_manager_default)) {
- simple_unlock(&vm_page_queue_free_lock);
- external = FALSE;
- goto again;
- }
-
/*
* TODO Find out what could cause this and how to deal with it.
* This will likely require an out-of-memory killer.
--
2.47.3