4 ms·
I've been a linux/osx user for 20+ years so I'm not familiar with Windows memory management. It'd be interesting to know why MS chose this approach and if it ha
by smodo 4y ago
I've been a linux/osx user for 20+ years so I'm not familiar with Windows memory management. It'd be interesting to know why MS chose this approach and if it has any benefits? Why not just let userspace request whatever it wants?
- jraph 4y agoWell, over-committing is an arguable choice. "Here's the memory you requested! I don't know if I have it available, but anyway. Here it is!" It turns out it probably works well/better in many cases, because apps don't actually use all the memory they request (up front), and for other reasons, but it's not the obvious choice to make. I would intuitively expect my OS to fail malloc if it does not have any enough memory available if I didn't know better. I would expect an OS capable of expending its swap file to try doing it before failing my malloc call though.
- mariusmg 4y ago>I would expect an OS capable of expending its swap file to try doing it before failing my malloc call though. It takes A LOT of time to expand the swap file. So failing malloc immeditately seems, to me, the right way to handle it. Maybe adding an optional callback to malloc to be notified when further allocations are possible would be a better way to handle this.
- jraph 4y ago> It takes A LOT of time to expand the swap file. So failing malloc immediately seems, to me, the right way to handle it. Maybe it'd be possible to check if expanding the swap file is possible, return and then actually expand the swap file when convenient. (I like being an armchair kernel developer :-))
- bogwog 4y agoBut 99.99999% of the time, when a program calls malloc, it needs it to succeed. So if there is a callback or something to notify that a wait is required or whatever, then 99.99999% of programs are going to do it. That means the high cost of expanding the swap file will be incurred basically every single time...so why not make that the default? In the rare case where a program wants to handle a failed allocation differently, then they should use a native system call that provides a more detailed interface than standard malloc. It doesn't matter if it's not portable since this is really a Windows-only thing. Crashing is not good for anyone. A temporary freeze sucks, sure, but that's what you get for not having enough memory. ...plus, it's not like random freezing is a foreign concept to Windows users.
- mbiondi 4y agoBut then we end up with the OOM Killer, which is awful - randomly kill the biggest process because "reasons".... It would be better if the OS could say no.
- aftbit 4y agoIn this case, the OOM Killer would be better, because a parent process is allowed to sacrifice one of its children, so the browser could kill the least-recently-used tab instead of itself. https://unix.stackexchange.com/questions/282155/what-is-the-out-of-memory-message-sacrifice-child https://unix.stackexchange.com/questions/282155/what-is-the-...
- dzaima 4y agoIf allocation predictably fails, you don't need an OS-level OOM killer to kill least-recently-used - you could just do said killing manually on failed allocation yourself. And you'd be able to do so in a much more controlled manner too while at it, instead of hoping the OS does what you want. (and if an OS/stdlib wanted to, such behavior could be made the default operation on allocation failure)
- BlueTemplar 4y agoNo, because you only have control over your own process (and its children) and not the others ?
- dzaima 4y agoRight, it wouldn't help when one process wants more memory but you want an unrelated one to get killed, but the question here was about a browser killing one of its own tabs instead of the main browser process dying. (though, for what its worth, in the case where processes themselves can't decide how to free memory, I, as the user, would much prefer to be given the option of what to kill anyway; linux completely fails to do that, and given that overcommitting affects DEs too, it'd be pretty complicated to allow for such a thing)
- pavon 4y agoYeah, I was pretty incredulous when I first discovered over-commit in Linux - I asked for memory and you gave it to me without an error, and now that I am deep in the guts of processing and can't easily recover, now you decide to tell me you don't really have it! But once you know about over-commit there are workarounds in languages where you control memory allocation, like touching every page right after you allocate it, but before using it. And in a garbage collected language you don't have any control or insight into when OOM exceptions will occur in either approach. So the ability for the OS to not trust lazy and greedy software that asks for memory but doesn't use it seems like a reasonable trade-off.
- AnIdiotOnTheNet 4y agoI don't think the reasonable solution is to, by default, lie to programs that care about memory allocation failure for the sake of those that don't.
- phs2501 4y agoI think one of the main reason overcommit is a thing on Linux (certainly one of the things one runs into if one turns it off) is dealing with the weirdness of fork()/exec(). For a moment there in between the two calls you _technically_ have double the RSS allocated - so spawning processes with fork()/exec() from a process with very large RSS is dicey if you don't want to technically overcommit the memory. Since 99.9% of the time very little of that memory is touched/COW'd before the exec() letting it overcommit rather than dying when a 4GB process tries to spawn a new child just because you don't have another spare 4GB of ram sitting around "just in case" is seen as a reasonable tradeoff. (Modulo vfork() and spawn() of course which are different and arguably better solutions to this issue.)
- ww520 4y agoThe Windows approach let you fail at a predictable place failing at the time of memory allocation. The overcommit approach causes OOM crashing at random places depending on how your program touches memory.
- godshatter 4y agoHere's my understanding: If you're over-committing memory then you don't find out your program ran out of memory until you try to access memory you've previously "allocated". If you're not over-committing, then you'll find out your program ran out of memory on an allocation where you might be better prepared to handle it.
- rkangel 4y agoOne thing it is worth noting is that the user experience on Windows of running out of memory is a lot better than on a Linux desktop environment. While things usually slow down due to a lot of swapping, the main UI continues to be functional enough to allow you to carry on using it and close things. Work is being done these days to improve the situation on Linux, but the default experience can be pretty painful. I was using Android Studio on a Fedora machine with on 8Gb of RAM, and sometimes the whole system would completely freeze for 10s of seconds at a time. This is not fun. Some references to work on Linux: https://lwn.net/Articles/317814/ https://lwn.net/Articles/317814/ https://fedoraproject.org/wiki/Changes/EnableEarlyoom https://fedoraproject.org/wiki/Changes/EnableEarlyoom
- tuetuopay 4y agoOTOH the mere existence of committed memory makes it hellish as a user when *something* leaks committed memory. You start getting out of memory errors while half of your RAM is empty, just because some half-assed driver somewhere leaks. To add insult to injury, task manager / resource monitor is always unable to show the exact process/driver that leaks; I had to randomly kill things to find the culprit. I'll take the linux behavior any time when dealing with poorly written software (which is most software).
- int_19h 4y agoWindows is strictly better here because 1) it will never pretend that it has more memory than it actually does, and yet 2) it allows processes to reserve as much address space as they need without using them (which is the sole justification for overcommit), by providing the APIs to control this in a fine grained way.
- xenadu02 4y agoThe Windows approach is better from a "perfect system" point of view: in theory an application knows all the code that it is loading and has a grasp on its own memory usage. You still have virtual address space because it is used for other things too (like memory mapped files), but you "commit" your current upper limit. You can be sure that if needed you'll actually be able to malloc (well HeapAlloc) that much memory. It might be slow due to swapping but it won't fail. The Unix approach is better from a "realistic" point of view: most processes have a lot of library code they don't control and don't have time to audit. Usage patterns vary. And most processes end up reserving more memory than they ever actually touch. Note what they mentioned in the article - 3rd party graphics drivers run code in every process on Windows and that code allocates whatever it wants that counts against your commit limit. That isn't under your control at all and worse most of the time the memory is never touched. Having lived under both systems I think I prefer the Unix view. In practice almost no Windows software does anything useful with commit limits so it just creates extra complexity and failure modes for little benefit.
- int_19h 4y ago> And most processes end up reserving more memory than they ever actually touch. I find this assertion dubious. Explicitly pre-allocating large arenas is common when micro-optimizing, which isn't something that happens for most apps out there - they just do the usual malloc/free (or equivalent) dance as needed. So for your average app, it boils down to the quality of implementation of its heap allocator. And there aren't that many of them to get right.