← Back to context

Comment by da_chicken

21 hours ago

Windows does freeze and become unstable, but it's usually because of some ring 0 errors not getting trapped appropriately.

But Windows has always handled both OOM and out of disk space very well. The system will be extremely sluggish, but it typically continues operating.

The Linux design is to keep using memory, then push to swap, and then when you OOM you hard lock. The built in kernel OOM module can miss when RAM usage spikes rapidly. You can enable OOM monitors like systemd-oomd or earlyoom, but they do not run by default, and their behavior is to term the offending process.

The thing about Windows is that when you request memory, you're only granted memory if it can be guaranteed in the first place. The application will get a "not enough memory" error. On Linux, you're permitted to request more memory than the system actually has, with the idea that you won't actually use that much memory. It's optimistic that way. But if you do use it, then you're screwed.

Doesn't Windows, like macOS, automatically expand swap? You can't run out of memory nearly as quickly as you can on Linux. And at least on Windows I always figured this is why it felt so sluggish under load--it ends up paging alot. Not sure why macOS has always felt more consistent; perhaps the OS and major apps are less gratuitous memory hogs?

  • If you're referring to Apple Silicon, my intuition is that the SoC design allows for higher bandwidth between SSD and RAM which reduces the performance impact of paging. I might be totally wrong though

Linux can be configured to disable memory overcommit

sysctl -w vm.overcommit_memory=2 sysctl -w vm.overcommit_ratio=50

It is probably a bad idea to do that though as it will limit the amount of virtual address space an application can use

  • Note that the fork()/execve() semantics of Linux pretty much depend on memory overcommit. You may get weird OOM crashes when there is seemingly no memory pressure, if you turn overcommit off.

    In the short time between fork() and execve(), the new process duplicates the entire virtual memory of the old one. None of this is physically allocated due to copy-on-write, but still all counts as virtual memory.

    • Has anybody tried a compromise? Like, the program forks and overcommit is ignored for it for a 1 second grace period? I know it would be more complicated than that, but something along those general lines.