Collin Funk wrote: > I also pushed the attached patch for NetBSD, since it feels fairly > straightforward. It only requires a single sysctl like the previously > used sysctl. > > Here is it compared to the output of 'top' on a NetBSD 10.1 VM: > > $ ./gltests/test-physmem > Total memory: 12884369408 B = 12287 MiB > Available memory: 12070146048 B = 11511 MiB > $ top | grep '^Memory:' > Memory: 196M Act, 21M Wired, 15M Exec, 168M File, 11G Free
Thanks. But it does not work right: The ability to run a program that uses a lot of memory also depends on the amount of available swap space. I did some experiments with 'test-vasnprintf-big2' that requires 25 GiB of memory: - 1 GiB swap: "killed: out of swap" - 17 GiB swap: "killed: out of swap" - 25 GiB swap: takes too long, machine nearly hung - 27 GiB swap: takes too long, machine nearly hung - 28 GiB swap: takes too long, machine nearly hung - 29 GiB swap: succeeds - 33 GiB swap: succeeds This patch roughly encodes the threshold (between 28 and 29 GiB of available swap space). Note that 'struct uvmexp' also contains a field 'swpgavail'. Its value is slightly larger than 'swpages - swpginuse'. So, we can use this formula swpages - swpginuse with a certain factor that represents the correspondence between the requested memory size (25 GiB) and the swap need (29 GiB). 2026-07-19 Bruno Haible <[email protected]> physmem: On NetBSD, consider the available swap space. * lib/physmem.c (physmem_claimable): Also consider the number of available swap pages. diff --git a/lib/physmem.c b/lib/physmem.c index ccfb596e42..9df908637b 100644 --- a/lib/physmem.c +++ b/lib/physmem.c @@ -312,7 +312,18 @@ physmem_claimable (double aggressivity) && len == sizeof uvmexp) { double pagesize = getpagesize (); - return (uvmexp.free + uvmexp.inactive) * pagesize; + /* On NetBSD, a process needs a number of memory pages and a comparable + number of swap pages. When not enough swap pages are available, the + process might be killed with "killed: out of swap", or the machine + might become unresponsive. */ + double available_memory_pages = uvmexp.free + uvmexp.inactive; + double available_swap_pages = + (unsigned long long) ((uvmexp.swpages - uvmexp.swpginuse) * 0.85); + double available_pages = + (available_memory_pages < available_swap_pages + ? available_memory_pages + : available_swap_pages); + return available_pages * pagesize; } } #endif
