kicking the can down the road means there isn't any longer a reasonable correction (failing the allocation), but instead we get to drive around randomly trying to find something to kill.
this is particularly annoying if you are running a service. there is no hope for it to recover - for example by flushing a cache. instead the OS looks around - sees this fat process just sitting there, and .. good news, we have plenty of memory now.
IIUC Linux was really the first OS to make overcommit so prominent. Most systems were a lot more conservative.
Somehow Solaris manages just fine.
And don't forget that swap memory exists. Ironically, using overcommit without swap is asking for trouble on Linux. Overcommit or no overcommit, the Linux VM and page buffer systems are designed with the expectation of swap.
Some other type of process like an interpreter that can subshell out doesn't know how big the allocation is going to get, would have to pre-fork early on.
In this way, you wouldn't "need" overcommit and the Linux horror of OOM. Well, perhaps you don't need it so badly. Programs that use sparse arrays without mmap() probably need overcommit or lots of swap.
https://www.kernel.org/doc/Documentation/vm/overcommit-accou...
We didn't actually want to fork anything and share gigabytes of virtual memory with the child process, we wanted to spawn an almost entirely independent process to do something and report results, but that got implemented under the hood by fork.
Spawning processes is one area where Windows is more elegant than linux: windows offers spawn. Apparently macos and solaris implement a posix_spawn that avoid the complications of fork/exec.
linux offers posix_spawn, apparently which may may or may not call fork under the hood depending on which libc you're using. If libc implements posix_spawn by calling fork then you're back in the same mess with linux heuristic memory accounting and overcommit. E.g. old versions of glibc will fork when you posix_spawn, newer versions of glibc may vfork . musl apparently will always vfork.
It looks like cpython's subprocess.Popen was patched in python 3.8 to detect some cases where posix_spawn can be used -- it reads as if it will only kick in on linux if it detects a sufficiently new version of glibc: https://github.com/python/cpython/blob/main/Lib/subprocess.p...
edit: Python 3.10 now supports using vfork for linux inside subprocess: https://bugs.python.org/issue35823
docker run --rm -it --entrypoint=/bin/sh python:3.9-alpine
# apk add strace
# strace python -c "import subprocess; subprocess.run(['ls', '-l'])" 2>&1 >/dev/null | grep fork
fork() = 88
docker run --rm -it --entrypoint=/bin/sh python:3.10-alpine
# apk add strace
# strace python -c "import subprocess; subprocess.run(['ls', '-l'])" 2>&1 >/dev/null | grep fork
vfork() = 15
edit 2: here's a similar tale from go, replacing use of fork in fork/exec:https://github.com/golang/go/issues/5838
https://go-review.googlesource.com/c/go/+/37439/
https://about.gitlab.com/blog/2018/01/23/how-a-fix-in-go-19-...
What if you are worried about both? ;-)
malloc() can tell everybody it has the memory but when push comes to shove the OS will have to admit overbooking.
Windows doesn’t do that. When you don’t have enough memory and not enough page file space either, these allocation functions usually do fail returning nullptr.
https://www.kernel.org/doc/Documentation/vm/overcommit-accou...
Also, I found this post that suggests Windows technically does overcommit memory, but only for stacks(‽): https://superuser.com/questions/1194263/will-microsoft-windo...
https://www.kernel.org/doc/Documentation/vm/overcommit-accou...
# free -h
total used free shared buff/cache available
Mem: 31Gi 3.1Gi 2.2Gi 27Mi 25Gi 27GiSwap: 15Gi 62Mi 15Gi
# uname -a
Linux athena 5.13.19-200.fc34.x86_64 #1 SMP Sat Sep 18 16:32:24 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
# gcc -o memaloc memaloc.c
# ./memaloc
error!
One approach is RSS, the memory in physical RAM... but what if you're swapping? Then again, maybe you swapped out memory you don't actually need and ignoring swap is fine.
The other approach is "how much memory you allocated", and then you hit fun issues mentioned in this article, like "the OS doesn't actually _really_ allocate until you touch the page".
(Longer version: https://pythonspeed.com/articles/measuring-memory-python/)
Alternatively use mmap & mlock to verify the allocation succeeded, but the process can still be OOM killed at any time for any reason.
It would not be very surprising if, once enough people come to depend on this, they break that, too.
It will absolutely fail (first because size_t is only 32b).
What's behind malloc() is what matters.
That being said, I never would have expected that code to ever succeed! Shows how much I take memory allocation for granted on more sophisticated systems. I can't remember the last time I malloc'd more than a few megabytes.
Things are a bit more complicated than that. Because RSS will contain memory mapped to your process that could also be mapped by other processes. That is the sum of RSS on your machine is also higher than your physical memory.
That includes libraries dynamically linked to your executable, but more importantly shared memory mmapped to your process.
A more "fair" estimate exists in the form of PSS (or USS), that will list all mapped regions from all process, and account each process a proportional share of the region.
e.g. If 2 processes mmap `/dev/shm/foo` of 1GB, both will inherit 500GB by PSS computation.
Kubernetes made writing poor code a breeze. At work we have microservices crashing 20 times a week but SLOs are not affected since traffic is routed to surviving pods. So we can concentrate on churning features fast instead of writing good code.
The real memory size of Safari is ~160MB but virtual memory size is 392GB which doesn't look right. I checked other processes and all the processes have similar virtual memory size which is around ~390GB.
I wonder if this is a bug in Activity Monitor or the virtual memory allocations really are this big for each process.
Everybody gets this wrong (which is funny for a binary question) but it starts an interesting discussion through which I hope to learn how much they know about OS and virtual memory.
I kept reading hoping that there was going to be a solution, but not really; there are comments discussing disabling overcommit, but even that's a tradeoff (it does fix this failure mode, but you might not want to actually run a system like that).