|
|
Log in / Subscribe / Register

Allowing small allocations to fail

Allowing small allocations to fail

Posted Mar 11, 2015 21:19 UTC (Wed) by wahern (subscriber, #37304)
In reply to: Allowing small allocations to fail by dlang
Parent article: Allowing small allocations to fail

memory overcommit is not your fundamental problem here. In fact, it help avoid the problem the vast majority of the time.

Isn't this basically the same logic used to justify mapping NULL to a read-only page filled with 0s? Which is what BSD did decades ago. It was a similarly poor design decision from the perspective of resilient systems and it took many years to undo.

Yes, the _majority_ of time you end up with benign behavior. The problem is the cases where you end up with completely wrong behavior. And the only way to solve _all_ the problems was for _everybody_ to write more robust code. The only way to coax code to become more robust was to make it fail spectacularly.

Have we forgotten about the very wise advice, fail fast, fail often?

The problem with overcommit and similar measures is that there's no incentive for people to write robust algorithms. Clearly the XFS people are in this camp. They didn't have to worry about it, so they didn't, and now their code is too complex to change.

You _can_ write robust algorithms resilient against low memory situations. Sometimes it's easy. RAII patterns simplify unwinding state, which is just as easy in C as in C++, minus the automatic destructors. Sometimes it's more difficult and might require rethinking your implementation in terms of an explicit state machine. Other times you must make a tradeoff between CPU cost and memory cost. Linux often already does this--for example using a O(2 log N ), cache-thrashing red-black tree instead of O(1), cache-friendly timing wheel for high resolution timers--but nobody really complains about it not being the absolute fastest possible because raw speed is rarely the _only_ consideration.

Not long ago people said that memory was cheap and worrying about memory constraints was a thing of the past. Then the embedded world exploded.

Properly handling OOM situations in core infrastructure code doesn't solve all the problems. But it's a prerequisite for solving all the problems. And we'll never make any headway as long as people can pass the buck to the OOM killer. The hierarchy of abstraction layers might not be so convoluted and poorly composable if they couldn't rely on simplifying assumption about memory allocation; the interfaces would have to been better designed to make unwinding state easier and make forward progress yieldable at a more fine-grained level.

Look at block devices. The reason we can't have non-blocking disk I/O is because Unix originally made the simplifying assumption that disk writes were per se non-blocking. The assumption was no doubt worthwhile back when it could reduce the complexity of your code by an order of magnitude. But now block device drivers are so complex anyhow that the cost+benefit tradeoff sucks. Same situation wrt to the big kernel lock. I would argue the same thing now applies to the OOM killer. The simplifying assumption has lost it's usefulness, presuming it was ever truly useful.


to post comments

Allowing small allocations to fail

Posted Mar 11, 2015 21:27 UTC (Wed) by dlang (guest, #313) [Link] (3 responses)

The problem here is not userspace and overcommit. The problem is in the kernel when it needs memory in order to write data to disk to allow it to free memory.

Causing users programs to fail more frequently, in the hope that developers will get better at handling the failures, is not going to make the slightest bit of difference to this problem.

Eliminating the OOM killer isn't going to address the problem of needing memory in order to free memory.

I'll also point out the backlash against ext4 for loosing data when programmers didn't properly use fsync. This isn't perceived by users as being a problem caused by the programmers of the application they are using, it's perceived as being a failure of the kernel.

Allowing small allocations to fail

Posted Mar 11, 2015 22:46 UTC (Wed) by wahern (subscriber, #37304) [Link] (2 responses)

Non-failing allocations in the kernel is part-and-parcel of the OOM killer. The whole point is that some kernel developers assume that if an allocation request fails, the OOM killer will free up some memory.

Of course failing allocations in user space won't fix XFS or other code. It won't fix user space applications, either. (FWIW, malloc could always fail in Linux because of process resource limits.)

But it does change expectations. In an OOM killer world you can make the assumption that if you're called from user space, then a small allocation could never fail because the OOK killer could always kill at least one user space application and thus free up some memory.

Without the OOM killer, XFS would have had to explicitly make arrangements to reserve a bounded amount of memory ahead of time, rather than implicitly relying on fuzzy assumptions.

XFS and similar code exists, and completely refactoring those things is clearly out of the question. But somebody has to pull the short straw and endure a little more pain than the others if and when Linux moves away from the allocations-cannot-fail simplifying assumption.

Allowing small allocations to fail

Posted Mar 12, 2015 0:08 UTC (Thu) by rgmoore (✭ supporter ✭, #75) [Link]

Without the OOM killer, XFS would have had to explicitly make arrangements to reserve a bounded amount of memory ahead of time, rather than implicitly relying on fuzzy assumptions.

I think you have the story backward here, at least in regard to XFS. The XFS developers did exactly what you suggested they should do, and reserved a pool of memory in advance in case memory got really tight. XFS would still work in the case that small allocations were allowed to fail, and they're actually the ones who started pushing to allow them to fail. The problem isn't that XFS never considered what to do if memory was really tight, but that their solution never goes into effect because the triggering case- a failed allocation- isn't allowed to happen.

Allowing small allocations to fail

Posted Mar 12, 2015 0:28 UTC (Thu) by dlang (guest, #313) [Link]

It's far more the case that filesystem developers are doing some really complex things that are really hard to roll back cleanly, and so they assume that some other kernel thread is going to be able to make progress and free some memory than that they assume that the OOM killer will free up memory for them.

I think it's a bad thing that this has grown to be as large and as common as it is. I just don't blame it on overcommit.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds