Live data from Hacker News

Vm.overcommit_memory=2 is the right setting for servers

ariadne.space

141–150 of 150 posts

Re: Vm.overcommit_memory=2 is the right setting for servers

#141

Earlier quoted context omitted.

> No non-embedded libc will actually return NULL This is just a Linux ecosystem thing. Other full size operating systems do memory accounting differently, and are able to correctly communicate when more memory is not available.

There are functions on many C allocators that are explicitly for non-trivial allocation scenarios, but what major operating system malloc implementation returns NULL? MSVC’s docs reserve the right to return NULL, but the actual code is not capable of doing so (because it would be a security nightmare).

> There are functions on many C allocators that are explicitly for non-trivial allocation scenarios, but what major operating system malloc implementation returns NULL?

Solaris (and FreeBSD?) have overcommitting disabled by default.

Re: Vm.overcommit_memory=2 is the right setting for servers

#142

Earlier quoted context omitted.

There are functions on many C allocators that are explicitly for non-trivial allocation scenarios, but what major operating system malloc implementation returns NULL? MSVC’s docs reserve the right to return NULL, but the actual code is not capable of doing so (because it would be a security nightmare).

> There are functions on many C allocators that are explicitly for non-trivial allocation scenarios, but what major operating system malloc implementation returns NULL? Solaris (and FreeBSD?) have overcommitting disabled by default.

Solaris, AIX, *BSD and others do not offer overcommit, which is a Linux construct, and they all require enough swap space to be available. Installation manuals provide explicit guidelines on the swap partition sizing, with the rule of thumb being «at least double the RAM size», but almost always more in practice.

That is the conservative design used by several traditional UNIX systems for anonymous memory and MAP_PRIVATE mappings: the kernel accounts for, and may reserve, enough swap to back the potential private pages up front. Tools and docs in the Solaris and BSD family talk explicitly in those terms. An easy way to test it out in a BSD would be disabling the swap partition and trying to launch a large process – it will get killed at startup, and it is not possible to modify this behaviour.

Linux’s default policy is the opposite end of that spectrum: optimistic memory allocation, where allocations and private mappings can succeed without guaranteeing backing store (i.e. swap), with failure deferred to fault time and handled by the OOM killer – that is what Linux calls overcommit.

Re: Vm.overcommit_memory=2 is the right setting for servers

#143
post #94

Earlier quoted context omitted.

> […] because after the fork writes to basically any page in either process will trigger memory commitment. This is largely not true for most processes. For a child process to start writing into its own data pages en masse, there has to exist a specific code path that causes such behaviour. Processes do not randomly modify their own data space – it is either a bug or a peculiar workload that causes it. You would have…

> This is largely not true for most processes. > In most scenarios, forking a process has a negligible effect on the overall memory consumption in the system. Yes, that’s what they’re getting at. It’s good overcommitment. It’s still overcommitment, because the OS has no way of knowing whether the process has the kind of rare path you’re talking about for the purposes of memory accounting. They said that disabling ove…

> […] the purposes of memory accounting.

This is a crucial distinction and I agree when the problem is framed this way.

The original statement by another GP, however, was that fork(2) is wasteful (it is not).

In fact, I have mentioned it in a sister thread that the OS does not have a way to know of the kind of behaviour the parent or the child will exhibit after forking[0].

Generally speaking, this is in line with the foundational ethos of the UNIX philosophy where UNIX gives its users a wide array of tools tantamount to shotguns that shoot both forward and backward simultaneously and the responsibility for with the number of deaths and permanent maimings ultimately lies with its users. In comparison, memory management in operating systems that run mainframes is substantially more complex and sophisticated.

[0] In a separate thread, somebody else has mentioned a valid reverse scenario where the child idles by after forking and it is the parent that makes its data pages dirty causing the physical memory consumption to baloon.

Re: Vm.overcommit_memory=2 is the right setting for servers

#144
I was just looking at an OOM situation this week. I disagree that turning overcommit off helps specifically with locality. Finding the straw that breaks the camel’s back doesn’t necessarily help you fix the problem. If you don’t understand the whole system, it’s going to be hard to debug regardless.

Re: Vm.overcommit_memory=2 is the right setting for servers

#145
> In contrast, when overcommit is enabled, the kernel simply allocates a VMA object without guaranteeing that backing memory is available: the mapping succeeds immediately, even though it is not known whether the request can ultimately be satisfied.

When overcommit is enabled, the kernel is allowed to engage in fractional reserve banking.

Re: Vm.overcommit_memory=2 is the right setting for servers

#146
post #96

Earlier quoted context omitted.

Also, > Thread stacks come up because reserving them completely ahead of time would incur large amounts of memory usage. Typically they start small and grow when you touch the guards. This is a form of overcommit. Ahead of the time memory reservation entails a page entry being allocated in the process’s page catalogue («logical» allocation), and the page «sits» dormant until it is accessed and causes a memory access…

I am aware reserving excess memory doesn't commit said memory. But it does reserve memory, which is what we were talking about. The point was that because you can have a lot of threads and restricting reserved stacks to some small value is annoying all systems overcommit stack. Windows initially commits some memory (reserving space in the page file/ram) for each but will dynamically commit more when you touch the gua…

> Idle threads do increase the amount of committed stack.

I am not clear on why the stack of an idlying thread would continue to grow. If a previously processed unit of work resulted in large amounts of memory pages backing the thread stack getting committed, then yes, it is not common to unmap the no longer required pages. It is a deliberate trade-off: automatic stack shrink is difficult to do safely and cheaply.

Idle does not actually make stacks grow, put simply.

> The nt kernel actually works similarly to Linux w.r.t. processes and threads.

Respectfully, this is slightly more that entirely incorrect.

Since Linux uses a single kernel abstraction («task_struct») for both processes and threads, it has one schedulable kernel object – «task_struct» – for both what user space calls a process and what user space calls a thread. «Process» is essentially a thread group leader plus a bundle of shared resources. Linux underwent the consolidation of abstractions in a quest to support POSIX threads at the kernel level decades ago.

Since fork(2) is, in fact, clone(2) with a bunch of flags, what you get depends on clone flags: sharing VM, files, FS context, signal handlers, and whether you are in the same thread group (CLONE_THREAD) and that creates a new thread group with its own memory management (but populated using copy-on-write), separate signal disposition context, etc.

Windows has two different kernel objects: a process (EPROCESS) and a thread (ETHREAD/KTHREAD). Threads are the schedulable entities; a process is the container for address space, handle table, security token, job membership, accounting, etc. They are tightly coupled, but not «the same thing».

On Windows, «CreateProcess» is heavier than Linux fork for structural reasons: it builds a new process object, maps an image section, creates the initial thread, sets up the PEB/TEB, initialises the loader path, environment, mitigations, etc. A chunk of that work is kernel-side and a chunk is user-mode (notably the loader and, for Win32, subsystem involvement). Blaming only «userspace» is wrong.

Defender (and third-party AV/EDR) can measurably slow process creation because it tends to inspect images, scripts, and memory patterns around process start, not because of deficiences of the kernel and system calls design.

Re: Vm.overcommit_memory=2 is the right setting for servers

#147
post #128

Earlier quoted context omitted.

OOM killer often doesn't run soon enough for me; I've even left the machine for twenty minutes and it's still swapping hard. And I do say "often" because it does sometimes work. I have set all my Firefox processes near-maximum priority to kill for the OOM killer, but it didn't help. Also don't forget about memory compression: only meaningful with overcommit.

Run without swap or with very little swap. I'm serious. Your modern server has enough memory, way more than 4MB, and you care about consistent latency don't you? Also, swap is wearing our your SSD.

You can't be serious having both 'your modern server has enough memory' and 'swap is wearing out your SSD' in the same sentence.

Even 0.3 DWPD drives have years before wearing out and in your modern server you really should have something with >= 1 DWPD.

Re: Vm.overcommit_memory=2 is the right setting for servers

#148
post #128

Earlier quoted context omitted.

OOM killer often doesn't run soon enough for me; I've even left the machine for twenty minutes and it's still swapping hard. And I do say "often" because it does sometimes work. I have set all my Firefox processes near-maximum priority to kill for the OOM killer, but it didn't help. Also don't forget about memory compression: only meaningful with overcommit.

They say swap is highly highly recommended even if you have plenty of memory. I don't care, I disable it anyway. Have been doing so for decades. Never caused a problem.

I would, but I have a hardware defect and can't use half my RAM slots, so I really don't have enough RAM. I have been considering a new laptop though (or just clean up my firefox tabs...)

Re: Vm.overcommit_memory=2 is the right setting for servers

#149
post #56

Earlier quoted context omitted.

Maybe it should use MAP_NORESERVE ?

I expect it does already, but I don’t think it would help here: > In mode 2 the MAP_NORESERVE flag is ignored. https://www.kernel.org/doc/Documentation/vm/overcommit-accou...

Hmm, we need setting 3 (more like 1.5) then.

Re: Vm.overcommit_memory=2 is the right setting for servers

#150
post #136
post #135

Earlier quoted context omitted.

I get that this is humorous, but it seems like it illustrates the point of why this strategy is useful in the first place: memory is not human life, does not feel pain, and can even be resurrected from swap (which might still take some extra time but still is way less of an issue than the corresponding problem for humans)? If the strongest objection to the system is that it can't be ethically generalized to apply to…

This is not about reclaiming memory by swapping the contents out to disk. It is about killing processes due to having overcommitted beyond the available memory plus swap space. The processes thrown out of the plane (targeted by the OOM killer) cannot be resurrected

Fair enough. I still think that the analogy is a bit overzealous given that my issue with the hypothetical weight-shedding strategy is ethical rather than technical.
Post reply on HN