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