Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Re: Improve uvm_pageout() logic for segmented memory space
To:
tech@openbsd.org
Date:
Thu, 7 Nov 2024 10:07:36 +0100

Download raw body.

Thread
On 06/11/24(Wed) 15:58, mpi@grenadille.net wrote:
> Diff below greatly improves the responsiveness of the page daemon for
> 64bit archs with a low/high memory split.  The improvement comes from
> a more precise calculation of how many low pages have to be freed.  As
> a result the amount of pages written to swap is decreased by ~50% in my
> tests and my arm64 machine becomes responsive during heavy swapping.
> 
> The diff includes:
> 
> - Use a global "struct uvm_pmalloc" to notify failed nowait allocations
>   in order to look at the managed lists.  The current algorithm does not
>   call uvmpd_scan() if there have been only nowait allocations.
> 
> - Skip calling the shrinkers and grabbing some locks if the page daemon
>   is awoken to rebalance the active/inactive lists.
> 
> - Do not bother releasing high pages if all we are interested in are low
>   pages
> 
> - Try to deactivate low pages first only if we are not short on swap
>   slots

First diff of the serie including some comments from miod@.

Introduce an helper to check if a page belongs to a given memory range.

diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c
index 8257140e6d6..46d3efae820 100644
--- a/sys/uvm/uvm_pdaemon.c
+++ b/sys/uvm/uvm_pdaemon.c
@@ -413,6 +413,23 @@ uvmpd_dropswap(struct vm_page *pg)
 	return result;
 }
 
+/*
+ * Return 1 if the page `p' belongs to the memory range described by
+ * 'constraint', 0 otherwise.
+ */
+static inline int
+uvmpd_match_constraint(struct vm_page *p,
+    struct uvm_constraint_range *constraint)
+{
+	paddr_t paddr;
+
+	paddr = atop(VM_PAGE_TO_PHYS(p));
+	if (paddr >= constraint->ucr_low && paddr < constraint->ucr_high)
+		return 1;
+
+	return 0;
+}
+
 /*
  * uvmpd_scan_inactive: scan an inactive list for pages to clean or free.
  *
@@ -440,7 +457,6 @@ uvmpd_scan_inactive(struct uvm_pmalloc *pma, int shortage,
 	boolean_t swap_backed;
 	vaddr_t start;
 	int dirtyreacts;
-	paddr_t paddr;
 
 	/*
 	 * swslot is non-zero if we are building a swap cluster.  we want
@@ -454,9 +470,7 @@ uvmpd_scan_inactive(struct uvm_pmalloc *pma, int shortage,
 
 	/* Start with the first page on the list that fit in `constraint' */
 	TAILQ_FOREACH(p, pglst, pageq) {
-		paddr = atop(VM_PAGE_TO_PHYS(p));
-		if (paddr >= constraint->ucr_low &&
-		    paddr < constraint->ucr_high)
+		if (uvmpd_match_constraint(p, constraint))
 			break;
 	}
 
@@ -865,7 +879,6 @@ uvmpd_scan(struct uvm_pmalloc *pma, int shortage, int inactive_shortage,
 	int swap_shortage, pages_freed;
 	struct vm_page *p, *nextpg;
 	struct rwlock *slock;
-	paddr_t paddr;
 
 	MUTEX_ASSERT_LOCKED(&uvm.pageqlock);
 
@@ -919,9 +932,7 @@ uvmpd_scan(struct uvm_pmalloc *pma, int shortage, int inactive_shortage,
 		/*
 		 * skip this page if it doesn't match the constraint.
 		 */
-		paddr = atop(VM_PAGE_TO_PHYS(p));
-		if (paddr < constraint->ucr_low &&
-		    paddr >= constraint->ucr_high)
+		if (!uvmpd_match_constraint(p, &pma->pm_constraint))
 			continue;
 
 		/*
-- 
2.46.1