0

I often want large, contiguous regions of virtual address space that can grow on demand. On Windows, I do this my calling VirtualAlloc with MEM_RESERVE and a dwSize argument that I think is larger than the region is reasonably likely to ever need to grow, then committing a page at a time as needed. Not only does this defer mapping pages to physical memory until they're accessed, which committing the whole region to begin with would also do, it also defers charging the pages against the system commit limit. That way, the program doesn't limit how much memory other programs are allowed to commit for the sake of memory it isn't yet using and may never use. Basically, I want to handle my program's memory management such that it is in principle allowed to consume a large amount of memory if the user's demands require it, while at the same time allowing other programs to have that memory instead if they need it first.

Someone has already asked whether macOS has an equivalent to VirtualAlloc with MEM_RESERVE. The answers suggest that mmap with MAP_ANON | MAP_PRIVATE is roughly equivalent. What I'm wondering is, does macOS have an equivalent to the Windows commit limit, and does mmap, called with the right flags, behave like my VirtualAlloc usage in not charging against that limit?

Edit: someone else asked a similar question about Linux, for which mmap was also suggested. The answer suggests that on that platform, initially mapping the region with PROT_NONE and adding the desired privileges when the pages are needed is necessary to prevent the unused pages from counting against the commit limit. Lacking better documentation about why mapping memory in excess of the available physical memory is allowed in macOS (complete lack of commit limit? some kind of overcommit feature like Linux has?), I figure I might as well apply the same PROT_NONE trick just in case. At the very least it means I will be able to reuse the same code for Linux should I choose to support that platform as well.

Alex Kindel
  • 173
  • 7

1 Answers1

1

I don't believe that macOS has a system commit limit. I don't find anything like that in the Mach APIs, which is the low-level VM API where I'd expect it to be. Likewise, I don't see anything like that in the output of sysctl -a, which reports many other VM details and statistics.

I can tell you for sure that I've reserved the entirety of the unused space in a 64-bit process (which has a 46-bit user address space). That is, just under 128TiB.

You can replicate that by just repeating mmap() calls with a large size until they fail, halve the size, and repeat, until your size is down to 1 page. Then, with the process paused at that point, apply vmmap -w -interleaved <pid> to it to see its allocations.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Huh! That surprises me because in Windows, as far as I know once you successfully commit a memory region, you have a guarantee that the system will be able to back it when needed; if you run out of memory, the failure corresponds to an explicit VirtualAlloc call you made, and the system can communicate the failure to you. With mmap on the other hand, it would seem that there is no stage at which you have a guarantee that the system will be able to back the virtual memory, and if it does run out, the failure doesn't correspond with any explicit call you made, so there is no hope of recovering. – Alex Kindel Nov 11 '19 at 02:31
  • Or maybe if mmap fails, it sets a global error code, and one could in principle check it each time one touches a new memory page? – Alex Kindel Nov 11 '19 at 02:35
  • Well, `mmap()` failing is separate from the whether the VM system will be able to fault in a page later. For anon, non-fixed mappings, `mmap()` with valid arguments can only fail if you exhaust the address space of your process. The VM system will always try to fault in pages you access. If necessary, it will swap out other pages to disk. Only if the boot drive is full could that fail. Before that, though, the system would likely have become unusable due to page thrashing. – Ken Thomases Nov 11 '19 at 02:55
  • I was thinking that the kind of failure explicit VirtualAlloc calls alert one of that mmap doesn't is the case where the boot drive is full, but I guess that isn't worth worrying about in practice. – Alex Kindel Nov 11 '19 at 03:01