aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2020-08-25 21:36:56 +0000
committerConrad Meyer <cem@FreeBSD.org>2020-08-25 21:36:56 +0000
commit74f5530d7a78d3be0055535e95bca4d520a01328 (patch)
treec7a19c30d9d30b936bc1c9827872ac74a0b60051
parent60403b98b907a7f80016de24e1770e323c3dcdbb (diff)
downloadsrc-74f5530d7a78d3be0055535e95bca4d520a01328.tar.gz
src-74f5530d7a78d3be0055535e95bca4d520a01328.zip
vm_pageout: Scale worker threads with CPUs
Autoscale vm_pageout worker threads from r364129 with CPU count. The default is arbitrarily chosen to be 16 CPUs per worker thread, but can be adjusted with the vm.pageout_cpus_per_thread tunable. There will never be less than 1 thread per populated NUMA domain, and the previous arbitrary upper limit (at most ncpus/2 threads per NUMA domain) is preserved. Care is taken to gracefully handle asymmetric NUMA nodes, such as empty node systems (e.g., AMD 2990WX) and systems with nodes of varying size (e.g., some larger >20 core Intel Haswell/Broadwell Xeon). Reviewed by: kib, markj Sponsored by: Isilon Differential Revision: https://reviews.freebsd.org/D26152
Notes
Notes: svn path=/head/; revision=364786
-rw-r--r--sys/vm/vm_pageout.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 34a3a4f9048e..c966c356908a 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -165,11 +165,10 @@ SYSCTL_INT(_vm, OID_AUTO, pageout_update_period,
CTLFLAG_RWTUN, &vm_pageout_update_period, 0,
"Maximum active LRU update period");
-/* Access with get_pageout_threads_per_domain(). */
-static int pageout_threads_per_domain = 1;
-SYSCTL_INT(_vm, OID_AUTO, pageout_threads_per_domain, CTLFLAG_RDTUN,
- &pageout_threads_per_domain, 0,
- "Number of worker threads comprising each per-domain pagedaemon");
+static int pageout_cpus_per_thread = 16;
+SYSCTL_INT(_vm, OID_AUTO, pageout_cpus_per_thread, CTLFLAG_RDTUN,
+ &pageout_cpus_per_thread, 0,
+ "Number of CPUs per pagedaemon worker thread");
SYSCTL_INT(_vm, OID_AUTO, lowmem_period, CTLFLAG_RWTUN, &lowmem_period, 0,
"Low memory callback period");
@@ -2200,38 +2199,38 @@ vm_pageout_helper(void *arg)
}
static int
-get_pageout_threads_per_domain(void)
+get_pageout_threads_per_domain(const struct vm_domain *vmd)
{
- static bool resolved = false;
- int half_cpus_per_dom;
+ unsigned total_pageout_threads, eligible_cpus, domain_cpus;
+
+ if (VM_DOMAIN_EMPTY(vmd->vmd_domain))
+ return (0);
/*
- * This is serialized externally by the sorted autoconfig portion of
- * boot.
+ * Semi-arbitrarily constrain pagedaemon threads to less than half the
+ * total number of CPUs in the system as an upper limit.
*/
- if (__predict_true(resolved))
- return (pageout_threads_per_domain);
+ if (pageout_cpus_per_thread < 2)
+ pageout_cpus_per_thread = 2;
+ else if (pageout_cpus_per_thread > mp_ncpus)
+ pageout_cpus_per_thread = mp_ncpus;
+
+ total_pageout_threads = howmany(mp_ncpus, pageout_cpus_per_thread);
+ domain_cpus = CPU_COUNT(&cpuset_domain[vmd->vmd_domain]);
+
+ /* Pagedaemons are not run in empty domains. */
+ eligible_cpus = mp_ncpus;
+ for (unsigned i = 0; i < vm_ndomains; i++)
+ if (VM_DOMAIN_EMPTY(i))
+ eligible_cpus -= CPU_COUNT(&cpuset_domain[i]);
/*
- * Semi-arbitrarily constrain pagedaemon threads to less than half the
- * total number of threads in the system as an insane upper limit.
+ * Assign a portion of the total pageout threads to this domain
+ * corresponding to the fraction of pagedaemon-eligible CPUs in the
+ * domain. In asymmetric NUMA systems, domains with more CPUs may be
+ * allocated more threads than domains with fewer CPUs.
*/
- half_cpus_per_dom = howmany(mp_ncpus / vm_ndomains, 2);
-
- if (pageout_threads_per_domain < 1) {
- printf("Invalid tuneable vm.pageout_threads_per_domain value: "
- "%d out of valid range: [1-%d]; clamping to 1\n",
- pageout_threads_per_domain, half_cpus_per_dom);
- pageout_threads_per_domain = 1;
- } else if (pageout_threads_per_domain > half_cpus_per_dom) {
- printf("Invalid tuneable vm.pageout_threads_per_domain value: "
- "%d out of valid range: [1-%d]; clamping to %d\n",
- pageout_threads_per_domain, half_cpus_per_dom,
- half_cpus_per_dom);
- pageout_threads_per_domain = half_cpus_per_dom;
- }
- resolved = true;
- return (pageout_threads_per_domain);
+ return (howmany(total_pageout_threads * domain_cpus, eligible_cpus));
}
/*
@@ -2288,7 +2287,7 @@ vm_pageout_init_domain(int domain)
"pidctrl", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
pidctrl_init_sysctl(&vmd->vmd_pid, SYSCTL_CHILDREN(oid));
- vmd->vmd_inactive_threads = get_pageout_threads_per_domain();
+ vmd->vmd_inactive_threads = get_pageout_threads_per_domain(vmd);
}
static void
@@ -2343,7 +2342,6 @@ vm_pageout(void)
p = curproc;
td = curthread;
- pageout_threads = get_pageout_threads_per_domain();
mtx_init(&vm_oom_ratelim_mtx, "vmoomr", NULL, MTX_DEF);
swap_pager_swap_init();
@@ -2363,6 +2361,7 @@ vm_pageout(void)
panic("starting pageout for domain %d: %d\n",
i, error);
}
+ pageout_threads = VM_DOMAIN(i)->vmd_inactive_threads;
for (j = 0; j < pageout_threads - 1; j++) {
error = kthread_add(vm_pageout_helper,
(void *)(uintptr_t)i, p, NULL, 0, 0,