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




Reply via email to