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


Reply via email to