NHacker Next
  • new
  • past
  • show
  • ask
  • show
  • jobs
  • submit
PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit (ubicloud.com)
ozgune 3 hours ago [-]
(Ozgun from Ubicloud)

I agree with the blog post's technical contents, but I feel we came across too strong in the title. For Ubicloud as a managed Postgres provider, we use strict memory overcommit. Our experience with operating Postgres at scale taught us that it's better to enable this than going with the defaults.

However, I can see many other scenarios, where using strict memory overcommit would have unanticipated side-effects. That's why Linux doesn't go with strict memory commit as its default.

furkansahin 3 hours ago [-]
(Furkan, submitter) Hmm, I haven’t thought about that. I updated the title to better reflect Ubicloud Postgres' position.
geraldwhen 29 minutes ago [-]
Is this an AI response?
furkansahin 15 minutes ago [-]
No.. But I have been using a lot of AI, recently. It might have impacted how I form my phrases? maybe?
leononame 3 hours ago [-]
This has bitten me multiple times. The problem I have is that at work we deploy the application (written in Go) and PostgreSQL on the same machine. The backend app allocates a lot of virtual memory, and initially we had overcommit to 0 (heuristic). This caused crashes on big queries in PostgreSQL and we set it to 2. The whole system became a bit unstable because the backend would still allocate a lot of virtual memory and at some point we ran into errors when allocating.

For now, we have overcommit_ratio set to a value that is stable from experience, but there really seems to be no silver lining. Go is very happy to allocate a lot of virtual memory, but so are most managed languages. The best solution would probably be to host the backend and the database on separate servers.

xyzzy_plugh 2 hours ago [-]
I'm not sure if you are aware but there are relatively recent environment variables you can set to help contain Go memory to a fixed size.

GOMEMLIMIT works very well if you set it to around 90% of available memory as a rough heuristic. You should definitely profile your application to fine tune this number (e.g. if you link with C libraries that hold large memory pools then Go doesn't account for that) but also to identify sources of spikey/leaky allocations. For example, encoding/json is notorious for it's inner sync.Pool hanging on to outsized buffers. There's usually a lot of low hanging fruit.

In my experience Go can be extremely stable in terms of memory footprint at both small (~O(1MiB)) and large (~O(256GiB)) scales, and it takes only a small amount of effort.

As far as GC languages go, it is by far the easiest to work with.

hilariously 3 hours ago [-]
Yes, it would. Basically every serious database tries to allocate everything and more - back in the day we'd just allocate VMs on the machine even with the overhead because knowing it cannot leave its constraints and would work within them was worth the cost.
guenthert 2 hours ago [-]
There are many reasons to use a dedicated host (or VM) for a DB server, but if only the accessible memory needs to be limited a container is the simpler, more efficient tool. Said that, I would expect to be able to configure how much memory a DB process is allowed to allocate. I remember distinctly that PostgreSQL allows such. But of course both can be configured simultaneously, a belts&suspenders approach if you will.

Whether failed transactions are actually so much more desirable than a OOM-killed process isn't quite obvious, but it might be easier to troubleshoot.

Bender 4 hours ago [-]
They allude to this in the article but I would emphasize caution when using mode 2 especially if one has already adjusted overcommit ratios as one can prevent forks. Test this in a QA/Perf environment first, also testing the restart of all applications. Load test and do full QA tests before deploying to Production and even then when deploying to production I would just dynamically change the setting via app deployment scripts until confidence is high instead of putting it in the sysctl config files.

I've gone through this exercise in the past on much older kernels which they cover as well and just me personally I ran into less issues by leaving overcommit to 0 and just dropping the overcommit ratio to 0 and setting the oom_score_adj for programs as high as 1000 if I wanted vmscan to leave them alone and of course using the Redhat formulas for setting vm.min_free_kbytes, vm.admin_reserve_kbytes, vm.user_reserve_kbytes. And of course be vigilant in disallowing app owners from using every last bit of memory.

Bender 1 hours ago [-]
Correcting a rather significant typo: setting the oom_score_adj for programs as high as 1000 should be -1000 to be left alone. 1000 would make it a prime candidate for an OOM kill. Positive integers should be used on sacrificial superfluous programs. [1] As an example OpenSSH sets the sshd to -1000 by default.

[1] - https://man7.org/linux/man-pages/man5/proc_pid_oom_score_adj...

wongarsu 59 minutes ago [-]
For once, Microsoft's decision to just not do overcommit in Windows seems sensible
chiply314 2 hours ago [-]
Nothing worse than memory management on Hyperscaler VMs which do not use Swap :|

Took k8s ages to get Swap support.

We lost something when we accepted that Hyperscalers just tell you to use more moemory. It was shitty 5 years ago and today especially after the ram price increases

ValdikSS 1 hours ago [-]
My guess would be: it's because memory management before MGLRU was really not good and required different userspace solutions and tinkering. You either get killed with OOM (no swap) or got into thrashing (swap).

And now, with PSI + MGLRU, situation is much better, but there are still missing features/subsystems which would be nice to have. For example there's no simple way to lock memory mlockall-style to ensure that rarely used daemon would not face long no-cache-latency upon accessing the first time after long idle time.

otterley 3 hours ago [-]
I think this is also a good lesson on why it's best to isolate mission-critical services like databases on their own compute nodes.
adamors 3 hours ago [-]
I read this article about 3 weeks ago when this bit me. Really great write-up, some tricky details.
3 hours ago [-]
szmarczak 3 hours ago [-]
I have disabled overcommit both on Windows and on Linux. I hate having random programs being killed.

Unfortunately, many programs commit 2x memory than they actually use. Often I see ~32GB committed and ~16GB resident.

sterwill 3 hours ago [-]
Does this result in programs more frequently erroring/crashing because they can't allocate? I don't know how well many of the programs I frequently use on my desktop (Firefox, GNOME desktop, JVM + IntelliJ, Slack, etc.) handle allocation failures. I'm not sure they would do much better than crash, but I know the default OOM killer settings work well for me. About once a year a real runaway process (usually a throwaway program I'm working on) gets OOM-killed, and that's fine with me.
szmarczak 51 minutes ago [-]
> Does this result in programs more frequently erroring/crashing because they can't allocate?

I run Firefox, VSCodium with LSP, Discord, Signal and there's still space left for a game like CS2. I'm not a heavy user by any means.

> I'm not sure they would do much better than crash

I have yet to see a program that silently handles allocation failures and doesn't crash. These days everything is coded to crash if no memory :(

> About once a year a real runaway process (usually a throwaway program I'm working on) gets OOM-killed

In my case it killed system critical processes with no way to recover. With disabled overcommit, it freezes for a while (usually for a minute or two), I close some random program of my choosing and then see in Resource Monitor what's eating my ram.

nok22kon 2 hours ago [-]
how exactly did you disabled it on Windows?

I dont think it has an option for that.

swinglock 54 minutes ago [-]
I don't think it has overcommit at all, at least that's the default. That would be why you don't have Windows OOM killer stories.
tredre3 40 minutes ago [-]
The reason you hear less about Window's OOM killer is simply because it works well.

The Linux Kernel OOM killer kills random things. Userspace OOM killers are meant to improve this, and they work well in a server situation when you already know in advance what is likely to go haywire and what is safe to kill. But they don't work well on desktop (some of them are improving but it doesn't seem to be a priority).

The Windows OOM killer by comparison usually kills something sensible (i.e. the program that is actually using all the memory), and asks the user for permission before killing it (when possible). You do see a lot of memes of situations where it fails.

nok22kon 33 minutes ago [-]
damn, good observation, when my data analysis python script goes wrong and allocates 24 GB of RAM on a 32 GB computer, it crashes (gets killed) with "out of memory" error. I've never seen something else getting killed
wongarsu 1 hours ago [-]
Not overcommitting is Windows's default and only behavior

A memory allocator can implement overcommit, because you can separate reserving virtual memory and having it backed by physical memory into two different system calls. But from the point of view of the kernel, any time it promises to give you physical memory that memory is backed either by RAM or by space reserved in the swap file

szmarczak 1 hours ago [-]
Settings -> View advanced system settings -> Performance (Settings) -> Advanced -> Virtual memory (Change...) -> No paging file
tredre3 43 minutes ago [-]
That's disabling swap, not overcommit. Windows doesn't overcommit. It's one of the reason why it handles low memory situations so much more gracefully than Linux.
0x1d7 40 minutes ago [-]
^

    The purpose of the system commit limit and commit charge is to track all uses of these resources to ensure they are never overcommitted — that is, that there is never more virtual address space defined than there is space to store its contents, either in RAM or in backing store (on disk).
- Windows Internals, 7th Edition
0x1d7 52 minutes ago [-]
This is almost always a bad idea.

If no memory is available where a page file would make a difference, this leads to application crashes instead. A crash is (usually) worse than paging.

Certain applications, Photoshop being the historical example, will outright fail to run with no page file present.

szmarczak 38 minutes ago [-]
> this leads to application crashes instead

Same happens if the page file is full. In that case, why don't those programs use disk directly instead?

No such problem would've ever occured if programs hadn't allocated more than they actually use.

toast0 16 minutes ago [-]
By default, windows uses an expandable page file.

Typically, performance drops enough that the user kills the program or reboots before the page file expands to fill the disk. And other threads here suggest there is something that will prompt users to kill programs in states like this.

> No such problem would've ever occured if programs hadn't allocated more than they actually use.

That's part of the issue, but sometimes things do in fact use too much memory as well as allocate too much.

Another part of the issue is that few programs are built to handle allocation failures.

And then you have a metrics issue. There's not really a good metric to know when you're out of memory, other than performance collapse. If your applications don't use disk, it's not too hard; but when they do use disk, performance will collapse once there's insufficient memory to provide the disk caching needed. In my experience, adding a small swap and monitoring swap i/o can be pretty helpful, and a small swap doesn't tend to allow long thrashing when memory use grows. But that's not universal and everybody loves to hate swap these days.

0x1d7 31 minutes ago [-]
Your argument falls flat when a page file can be multi-GB and automatically grow. And if your application admin was competent, memory monitoring would be part of the application monitoring stack.

An application that grows in such a way (besides having backing stores for memory-mapped files, as well) will often perform so poorly that it requires addressing (adding RAM, looking for application faults, etc).

A page file is insurance, one that can last you much longer than available system memory.

szmarczak 4 minutes ago [-]
> memory monitoring would be part of the application monitoring stack

You don't need it if you have everything allocated upfront. TigerBeetle does this, everybody else can.

Using something like Rust is already a huge win when compared to shipping a browser or running Node.js.

> Your argument falls flat when a page file can be multi-GB and automatically grow

This doesn't solve the original issue and only masks the underlying problem.

swordlucky666 3 hours ago [-]
[dead]
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact
Rendered at 17:09:22 GMT+0000 (Coordinated Universal Time) with Vercel.