4 ms·
I am not sure how you can make a user friendly application like that. How about an image viewer that tries to open too large an image, should it just crash whe
by SigmundA 5y ago
I am not sure how you can make a user friendly application like that.
How about an image viewer that tries to open too large an image, should it just crash when it OOMs? I would much prefer an error dialog and the program continues to run.
- lmilcin 5y agoUsers are aware things stop working when memory is exhausted. As a user I am ok with this. I don't let my memory end and would prefer that the application worked reliably while there is still memory. What I don't like is applications trying to pretend nothing happened but then doing some strange shit. I have seen, for example, applications using 100% cpu after they hit OOM. Yes they survived. No, it is not user friendly.
- SigmundA 5y agoWhy would users be aware what happened? Did you tell them? This is a very reliable and easy for the user and other developers to understand. try { image = LoadImage(path); } catch(OutOfMemoryException e) { Msgbox("Cannot load image it is too large for available memory"); } That is way more friendly than a program crash and allow the user to try again perhaps with a smaller version of the image because they accidentally picked the high res version or something. Either way you may get 100% CPU as the program crashes and memory gets reclaimed, or the program continues to run and the garbage collector reclaims.
- XorNot 5y agoAlthough you've encoded the whole problem right there: do you even have enough memory to setup a MsgBox widget or whatever that is?
- SigmundA 5y agoIn a GC'd language which is what I am used to, the GC will pause execution and reclaim on the next allocate if there isn't any available memory cleaning up whatever was allocated on the attempted image load. After that if there is still not enough memory for the simple message box then you have an uncaught exception and the program crashes and you're just back to the no catch approach, nothing lost. Most likely though there will be enough memory for the message and you have a much more friendly result. I have used this approach before and it is way way more friendly then a crash with users potentially losing work because they accidentally picked the wrong file.
- lmilcin 5y ago> After that if there is still not enough memory for the simple message box (...) That's exactly the point. Once memory is exhausted, you can't take any action reliably. You don't build reliable applications by making mechanisms like: "ok, if memory ends lets design it to show a box to the user, we have 50% chance this succeeds". It would be better to wrap your application in a script that detects when the application quit and only then shows a message to the user. People designing things like you drive me crazy. They come up with a huge number of contingencies that just don't work in practice when push comes to shove. Stuck in a loop trying to show a widget, using 100% of CPU and preventing me to do any action? I prefer simpler mechanisms that work reliably.
- dnautics 5y agoAll critical paths, should be allocated on application start, and you never have to worry about that.
- lmilcin 5y agoThis is the kind of advice that I put in a category of "easier said than done". The trouble is that you may not know beforehand what exactly is going to be needed. And you might need maybe a library call and the library does dynamic allocation in it and you either have no idea about it (until you find out the hard way) or no way to help it. So in the end maybe you can take some extremely simple action like writing something to log or show a widget, but that's about it.
- dnautics 5y agoJust code as normal and when you run into a problem, reassign the default allocator for the struct/object? Not possible for many PLs, hard for some but basically trivial (1 LOC per struct/object) for others. Some PLs come with test suites that give you a failing allocator, so you can even easily test to make sure this looping condition resolves sanely.
- SigmundA 5y ago
- dnautics 5y agoPreallocate that? If it's modal, you should never have more than one, and the allocator associated with the msgbox should know to use that scratch space instead of fetching new memory. This is nontrivial in several PLs.
- ectopod 5y agoFor big infrequent allocations (like your example of loading a huge image) it is easy to use a non-default allocator that returns an error rather than aborting. As the article notes, this is all moot if you are running on Linux though. The allocation will always succeed but if it's too big the kernel will start killing processes, quite possibly including your image viewer.
- beached_whale 5y agooom handling on linux is a system option and there are also ulimits
- alerighi 5y agoIn Linux allocations can fail in some situation, for example in case it's set a resource limit on memory, because it was set a memory rlimit for the process, or the cgroup that contains the process runs out of memory (so if you run the program in a container with constrained memory).
- tooltower 5y agoYou can look at the SQLite codebase for good examples of this. Essentially, you will have to introduce a fixed upper bound for the file size you are willing to handle, given your minimum system requirements. This way, you can actually test that your program gracefully handles OOM conditions. This page explains more on this: https://sqlite.org/limits.html https://sqlite.org/limits.html
- SigmundA 5y agoFixed upper limits are helpful but do not prevent OOM. Perhaps the system has very little free memory due to other programs or limited hardware or other reasons but your program is intended to load large files on systems that have the memory so the upper limits are pretty high. It's takes very little memory to show the user an error message it will almost always succeed even if the operation that triggered failed due to OOM.
- tooltower 5y agoOf course, it's not a guarantee. But if your program is under heavy pressure from other programs, it won't continue to run in any reasonable sense either, even without Linux's OOM-killer. Yes, you can show an error message, but then the only safe thing to do is quit. You won't even be able to clean up any on-disk swap files properly, let alone handle user interactions. Handling this is hard in desktop applications. For servers, you can have known workloads with better limits on each process.
- kragen 5y agoThat is what Linux's OOM killer does, yes. In Linux you can handle the problem by spawning off a subprocess and watching to see why it dies. Not an acceptable result for your antilock braking system firmware.