19 comments

[ 2.9 ms ] story [ 48.8 ms ] thread
The swap/memory situation in linux has surprised me quite a bit coming from Windows.

Windows remains mostly fully responsive even when memory is being pushed to the limits and swapping gigabytes per second, while on linux when I ran a stress test that ate all the memory I had trouble even terminating the script

I've had that same experience. On new systems I install earlyoom. I'd rather have one app die than the whole system.

You'd think after 30 years of GUIs and multi-tasking, we'd have this figured out, but then again we don't even have a good GUI framework.

There's two things that cause this. First, Windows has a variable swap file size, whereas Linux has a fixed size, so Windows can just fill up your drive, instead of running out of swap space. Second, the default behavior for the out-of-memory killer in Linux isn't very aggressive, with the default behavior being to over-commit memory instead of killing processes.

As far as I know, Linux still doesn't support a variable-sized swap file, but it is possible to change how aggressively it over-commits memory or kills processes to free memory.

As to why there differences are there, they're more historical than technical. My best guess is that Windows figured it out sooner, because it has always existed in an environment where multiple programs are memory hogs, whereas it wasn't common in Linux until the proliferation of web-based everything requiring hundreds of megabytes to gigabytes of memory for each process running in a Chrome tab or Electron instance, even if it's something as simple as a news article or chat client.

Check out this series of blog posts. for more information on Linux memory management: https://dev.to/fritshooglandyugabyte/series/16577

There are some mistakes in these blog posts, especially the one about overcommit.
The annoying thing I've found with Linux under memory stress (and still haven't found a nice way to solve) is I want it to always always always kill firefox first. Instead it tends to either kill nothing (causing the system to hang) or kill some vital service.
> Windows remains mostly fully responsive even when memory is being pushed to the limits and swapping gigabytes per second

In my experience this is only on later versions of the NT Kernel and only on NVME (mostly the latter I think).

In Linux the default swap behaviour is to also swap out the memory mapped to the executable file, not just memory allocated by the process. This is a relatively sane approach on servers, but not so much on desktops. I believe both Windows and macOS don't swap out code pages, so the applications remain responsive, at the of (potentially) lower swap efficiency
> In Linux the default swap behaviour is to also swap out the memory mapped to the executable file, not just memory allocated by the process […] I believe both Windows and macOS don't swap out code pages, so the applications remain responsive, at the of (potentially) lower swap efficiency

Linux does not page out code pages into the swap. You might be conflating page reclamation with swapping instead.

In Linux, executable «.text» pages are mapped[0] as file-backed pages, not anonymous memory, so when the kernel needs to reclaim RAM it normally drops those pages and reloads them from the executable file on the next page fault once they are accessed again (i.e. on demand) rather than writing them to swap.

In this particular regard, Linux is no different from any other modern UNIX[1] kernel (*BSD, Solaris, AIX and may others).

[0] Via mmap(2) in argv[0], essentially.

[1] Modern UNIX is mid-1990's and onwards.

It seems to be a persistent myth. The Linux kernel explicitly excludes active VM_EXEC pages from reclaim.
Oh yeah. Bug 12309 was reported now what, 20 years ago? It’s fair to say that at this point arrival of GNU Mach will happen sooner than Linux will be able to properly work under memory pressure.
> Windows remains mostly fully responsive even when memory is being pushed to the limits and swapping gigabytes per second ...

The problem problem though is all the times when Windows is totally unusable even though it's doing exactly jack shit. An example would be when it's doing all its pointless updates/upgrades.

I don't know what people are smoking in this world when they somehow believe that Windows 11 is an acceptable user experience and a better OS than Linux.

Somehow though it's Linux that's powering billions if not tens of billions of devices worldwide and only about 12% of all new devices sold worldwide are running that piece of turd that Windows is.

OOM killers serve a purpose but - for a desktop OS - they're missing the point.

In a sane world the user would decide which application to shut down, not the OS; the user would click the appropriate application's close gadget, and the user interface would remain responsive enough for that to happen in a matter of seconds rather than minutes.

I understand the many reasons why that's not possible, but it's a huge failing of Linux as a desktop OS, and OOM killers are picking around the edges of the problem, not addressing it head-on.

(Which isn't to say, of course, that OOM killers aren't the right approach in a server context.)

OpenBSD and the rest have a limits file where you can set RAM limits per user and sometimes per process, so is not a big issue.

On GNU/Linux and the rest not supporting dynamic swap files, you can swap into anything ensembling a file, even into virtual disk images.

Also set up ZRAM as soon as possible. 1/3 of the physical RAM for ZRAM it's perfect, it will almost double your effective RAM size with ease.

systemd allows setting cgroup memory limits.
Is there a reason as to why Linux has not adopted straight up page compression like Windows and macOS?
I see some comments about soft lockups during memory pressure. I have struggled with this immensely over the years. I wrote a userspace memory reclaimer daemon and have not had a lockup since: https://gist.github.com/EBADBEEF/f168458028f684a91148f4d3e79... .

The hangs usually happened when I was stressing VFS (the computer was a samba server) along with other workloads. To trigger a hang manually I would read in large files (bigger than available ram) in parallel while running a game. I could get it to hang even with 128GB ram. I tweaked all the vfs settings (swappiness, etc...) to no avail. I tried with and without swap.

In the end it looked like memory was not getting reclaimed fast enough, like linux would wait too long to start reclaiming memory and some critical process would get stuck waiting for some memory. The system would hang for minutes or hours at a time only making the tiniest of progress between reclaims.

If I caught the problem early enough (just as everything started stuttering) I could trigger a reclaim manually by writing to '/sys/fs/cgroup/memory.reclaim' and the system would recover. I wonder if it was specific to btrfs or some specific workload pattern but I was never able to figure it out.

Just tune the kernel watermarks - vm.min_free_kbytes and vm.watermark_scale_factor
I do wish I had documented what I tried better! There might be a magic combo that could have helped but I tried tweaking a lot of the vm settings.

One day I will probably see if I can still reproduce the original problem and be more methodical about it. More likely on list of things I might not ever get around to.

The new design is still wrong though - the swap system is a cache, there's no reason why a page should only exist on one level.