Remix.run Logo
zozbot234 4 days ago

> I a hypothetical case without swap this case isn't so painful. When main system memory is almost fully consumed, OOM killer kills the most memory hungry program

That's not how it works in practice. What happens is that program pages (and read-only data pages) get gradually evicted from memory and the system still slows to a crawl (to the point where it becomes practically unresponsive) because every access to program text outside the current 4KB page now potentially involves a swap-in. Sure, eventually, the memory-hungry task will either complete successfully or the OOM killer will be called, but that doesn't help you if you care about responsiveness first and foremost (and in practice, desktop users do care about that - especially when they're trying to terminate that memory hog).

Panzerschrek 3 days ago | parent [-]

Why not just always preserving program code in memory? It's usually not that much - typical executable is usually several megabytes in size and many processes can share the same code memory pages (especially with shared libraries).

creshal 3 days ago | parent | next [-]

> It's usually not that much - typical executable is usually several megabytes in size and many processes can share the same code memory pages (especially with shared libraries)

Have a look at Chrome. Then have a look at all the Electron "desktop" apps, which all ship with a different Chrome version and different versions of shared libraries, which all can't share memory pages, because they're subtly different. You find similar patterns across many, many other workloads.

teddyh 3 days ago | parent [-]

Or modern languages, like Rust and Go, which have decided that runtime dependencies are too hard and instead build enormous static binaries for everything.

inkyoto 3 days ago | parent | prev | next [-]

> Why not just always preserving program code in memory?

Because the code is never required in its entirety – only «currently» active code paths need to be resident in memory, the rest can be discarded when inactive (or never even gets loaded into memory to start off with) and paged back into memory on demand. Since code pages are read only, the inactive code pages can be just dropped without any detriment to the application whilst reducing the app's memory footprint.

> […] typical executable is usually several megabytes

Executable size != the size of the actually running code.

In modern operating systems with advanced virtual memory management systems, the actual resident code size can go as low as several kilobytes (or, rather, a handful of pages). This, of course, depends on whether the hot paths in the code have a close affinity to each other in the linked executable.

man8alexd 3 days ago | parent | prev [-]

Programs and shared libraries (pages with VM_EXEC attribute) are kept in the memory if they are actively used (have the "accessed" bit set by the CPU) and are least likely to be evicted.