9

When I try to do a calculation that needs to allocate and use 128 GB of memory (it is a command line program written in C), the kernel kills my process with extreme prejudice. This console log entry is an example of one instance:

9/25/15 7:08:40.000 PM kernel[0]: low swap: killing pid 6202 (huffgrp)

The calculation works fine and in a reasonable amount of time when it allocates and uses 64 GB of memory. My machine has 32 GB of RAM and beaucoup space on the hard drive. I also tried this on another machine with 8 GB of RAM, on which the 64 GB calculation runs fine as well, taking longer of course, but the 128 GB calculation gets killed by the kernel in the same way. On both I am running Yosemite 10.10.5.

By the way, malloc() never returns an error, no matter how much space I ask for. The kernel will only kill the process once too much of that memory is actually being used by the process, resulting in lots of swapping to the hard drive.

So there appears to be a secret swap space limit somewhere between 64 GB and 128 GB.

My question is: how do I reconfigure the kernel to permit more swap space? I found a promising looking file, /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist, but I don't see the secret number in there. The man page for dynamic_pager says that all it does is set the name and location of the swap files. There is an older version of the same man page that documents a -S option to set the size of the swapfiles created. I tried that, requesting 160 GB swapfiles, but it had no effect. The swapfiles were still 1 GB each, and the process was still killed by the kernel.

2
  • 1
    Please don't cross-post (unix.stackexchange.com/questions/232362/…). If you think another SE site is better suited to get an answer, we can easily help you to migrate it.
    – nohillside
    Sep 27, 2015 at 19:26
  • 7
    The site that's best suited to get an answer is the one that I get an answer on. However there is no way to know which site that is without trying. If I would like an answer soon, why should I be constrained to only fish in one pond, and then wait some indeterminate time to conclude that there will be no bites before trying another pond? This question is well suited to both sites. Come to think of it, the answer would be useful on both sites as well. So why shouldn't the eventual answer be duplicated on the two sites? The Venn diagram overlap between these sites is quite large.
    – Mark Adler
    Sep 27, 2015 at 20:29

2 Answers 2

5

Well, it's been 7 years after this question was asked, but I just spent quite some time on this question, and at least as of Jun 2021 (macOS Monterey, commit 2ff845c2), the swap size limit is hardcoded 100 GB (100 files, 1 GB each). The behavior I observe on Ventura seems identical.

See vm_compressor_backing_store.c line 150:

#define VM_MAX_SWAP_FILE_NUM            100

and vm_compressor_backing_store.h line 50:

#define MAX_SWAP_FILE_SIZE              (1 * 1024 * 1024 * 1024ULL)

Lines are copied for clarity, but these line numbers can't change because the links point to the specific commit hash.

3
  • Thanks for taking time to dig into this! I hope you were motivated by something more than just my question here. Interestingly my Mac Studio with 128GB of physical RAM seems to have more swap space. I was able to run that same program to completion using 256GB of memory, which must have instantiated more than 100GB of swap space. It was unceremoniuosly killed, as before, but now not until I tried to use 512GB of memory. I am running macOS Ventura 13.3.1.
    – Mark Adler
    Apr 15 at 21:17
  • @MarkAdler The swap file on Mac is compressed, which typically provides about 2x more space. If you fill it uniformly (like with 1s), I believe it’s possible to reach single-digit TBs of allocated memory :) I took special care to fill the memory with random bytes for my tests. Also, I can explain how to watch the number/size of swap files dynamically, so we can do tests on your Mac, if you want :)
    – wizzard0
    Apr 16 at 22:08
  • Ok. My data is in fact quite compressible.
    – Mark Adler
    Apr 16 at 23:08
3

While I could not find any more recent documentation, Singh's "Mac OS X Internals: A Systems Approach" mentions two obscure limits in /sbin/dynamic_pager (p. 919 f.):

  • The absolute minimum and maximum swap file sizes are 64MB and 1GB, respectively.

  • The maximum swap file size must not be greater than 12.5% of the free space available on the volume that contains the swap file. Moreover, the maximum swap file size must not be greater than the amount of physical memory on the system.

  • At most, eight swap files can be created.

[...]

While the book is a bit dated and the numbers are likely to have changed, the 12.5% rule sounds very suspicious to me.

Singh implies that those are hard-coded limits in the binary and thus the property file you found is likely not to be of use. Also note that the swap system creates several, but only up to eight, distinct swap files.

/sbin/dynamic_pager is documented, as you noted, as a very rudimentary man page, and there is a conflicting statement in the current developer documentation on Virtual Memory, stating that

To give processes access to their entire 4 gigabyte or 18 exabyte address space, OS X uses the hard disk to hold data that is not currently in use. As memory gets full, sections of memory that are not being used are written to disk to make room for data that is needed now. The portion of the disk that stores the unused data is known as the backing store because it provides the backup storage for main memory.

[...]

Note: Unlike most UNIX-based operating systems, OS X does not use a preallocated disk partition for the backing store. Instead, it uses all of the available space on the machine’s boot partition.

(emphasis mine)

Hence, at around this point, I'd go for some pragmatic workaround. Perhaps try increasing your disk space even further to check for a correlation in the obtainable swap size, thus checking the 12.5% limitation mentioned above.

1
  • Thank you for the research. +1 for that. Doing nothing, I am able to get at least 64 GB of swap space, so the limit of 1 GB per swapfile times eight swapfiles must be out of date. I tried this on a machine with 2.2 TB free on the boot drive with the same results, so the free space is not the limiting factor. I did attempt a workaround where I created my own virtual memory file using mmap(). Unfortunately I discovered that it is subject to the same limits. Which in retrospect should not be surprising, since malloc() is implemented using mmap().
    – Mark Adler
    Dec 23, 2015 at 16:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .