Memory-mapped files and low-memory scenarios

14,340

Solution 1

Memory-mapped files copy data from disk into memory a page at a time. Unused pages are free to be swapped out, the same as any other virtual memory, unless they have been wired into physical memory using mlock(2). Memory mapping leaves the determination of what to copy from disk to memory and when to the OS.

Dropping from the Foundation level to the BSD level to use mmap is unlikely to make much difference, beyond making code that has to interface with other Foundation code somewhat more awkward.

Solution 2

(This is not an answer, but it would be useful information.)

From @ID_AA_Carmack tweet,

@ID_AA_Carmack are iOS memory mapped files automatically unmapped in low memory conditions? (using +[NSData dataWithContentsOfMappedFile]?)

ID_AA_Carmack replied for this,

@KhrobEdmonds yes, that is one of the great benefits of using mapped files on iOS. I use mmap(), though.

I'm not sure that is true or not...

Solution 3

From my experiments NSData does not respond to memory warnings. I tested by creating a memory mapped NSData and accessing parts of the file so that it would be loaded into memory and finally sending memory warnings. There was no decrease in memory usage after the memory warning. Nothing in the documentation says that a memory will cause NSData to reduce real memory usage in low memory situations so it leads me to believe that it does not respond to memory warnings. For example NSCache documentation says that it will try and play nice with respect to memory usage plus I have been told it responds to the low memory warnings the system raises.

Also in my simple tests on an iPod Touch (4th gen) I was able to map about 600 megs of file data into virtual memory use +[NSData dataWithContentsOfMappedFile:]. Next I started to access pages via the bytes property on the NSData instance. As I did this real memory started to grow however it stopped growing at around 30 megs of real memory usage. So the way it is implemented it seems to cap how much real memory will be used.

In short if you want to reduce memory usage of NSData objects the best bet is to actually make sure they are completely released and not relying on anything the system automagically does on your behalf.

Solution 4

If iOS is like any other Unix -- and I would bet money it is in this regard -- pages in an mmap() region are not "swapped out"; they are simply dropped (if they are clean) or are written to the underlying file and then dropped (if they are dirty). This process is called "evicting" the page.

Since your memory map is read-only, the pages will always be clean.

The kernel will decide which pages to evict when physical memory gets tight.

You can give the kernel hints about which pages you would prefer it keep/evict using posix_madvise(). In particular, POSIX_MADV_DONTNEED tells the kernel to feel free to evict the pages; or as you say, "mark pages as being no longer in use".

It should be pretty simple to write some test programs to see whether iOS honors the "don't need" hint. Since it is derived from BSD, I bet it will.

Solution 5

Standard virtual memory techniques for file-backed memory says that the OS is free to throw away pages whenever it wants because it can always get them again later. I have not used iOS, but this has been the behavior of virtual memory on many other operating systems for a long time.

The simplest way to test it is to map several large files into memory, read through them to guarantee that it pages them into memory, and see if you can force a low memory situation. If you can't, then the OS must have unmapped the pages once it decided that they were no longer in use.

Share:
14,340
Sedate Alien
Author by

Sedate Alien

Updated on June 04, 2022

Comments

  • Sedate Alien
    Sedate Alien about 2 years

    How does the iOS platform handle memory-mapped files during low-memory scenarios? By low-memory scenarios, I mean when the OS sends the UIApplicationDidReceiveMemoryWarningNotification notification to all observers in the application.

    Our files are mapped into memory using +[NSData dataWithContentsOfMappedFile:], the documentation for which states:

    A mapped file uses virtual memory techniques to avoid copying pages of the file into memory until they are actually needed.

    Does this mean that the OS will also unmap the pages when they're no longer in use? Is it possible to mark pages as being no longer in use? This data is read-only, if that changes the scenario. How about if we were to use mmap() directly? Would this be preferable?

  • Jeremy W. Sherman
    Jeremy W. Sherman about 13 years
    You might find mincore useful to test whether a page is swapped out or not.
  • Sedate Alien
    Sedate Alien about 13 years
    Thanks for your answer, Jeremy. I understand that using mmap'ed files leaves the OS with greater control, but my question relates to how iOS specifically handles this. Is my only option to test experimentally and use mincore (very useful, thanks!) as you suggested in your comment?
  • Sedate Alien
    Sedate Alien about 13 years
    I might have to go down that path and see what I can determine experimentally. I asked my question as it appears that iOS does not strictly adhere to "standard virtual memory techniques" and does not page out unused memory to disk, etc and I wondered how this might translate to mmap'ed files.
  • Jeremy W. Sherman
    Jeremy W. Sherman about 13 years
    Unfortunately, iOS's source code is not public. Darwin, which is the base of Mac OS X and is very similar to iOS, does have public source, so you can look at that; you'd probably just need to look at the xnu package. Aside from that, your only options are experimentation and reverse engineering, and the former is likely to be faster, if not quite as much fun.
  • Jeremy W. Sherman
    Jeremy W. Sherman about 13 years
    Also, though you might be able to determine how iOS behaves now, unless there's some sort of promise of that behavior (standards compliance, Apple documentation), future versions of iOS will be free to behave differently.
  • DarkDust
    DarkDust about 13 years
    Since the question wasn't completely answered (we still don't have confirmation whether it behaves as you suspect) I'll let the bounty expire which will award you 25 points. Also I did +1 on the question which nets in 35 points for you, hope that's alright with you.
  • Jeremy W. Sherman
    Jeremy W. Sherman about 13 years
    @DarkDust No problem. At this point, I'd hope OP would perform the profiling needed to determine how iOS behaves, and then edit the question or add a comment with the results.
  • DarkDust
    DarkDust about 13 years
    +1, If John Carmack confirms it it's almost as good as confirmation from Apple to me ;-) He tests stuff and knows what he's talking about.
  • Sedate Alien
    Sedate Alien over 12 years
    I think that's because it's been replaced by +[NSData dataWithContentsOfFile:options:error:], which supports mapped files.
  • some_id
    some_id over 12 years
    Yes, the virtual memory will be paged into RAM until the calculated RAM limit is reached. Further data requests located in virtual memory would force the kernel to page out inactive data, starting with chunks marked appropriately. Knowingly using virtual memory mapped data is not really relying on kernel magic :D
  • some_id
    some_id over 12 years
    Well, that was available since iOS 2.0. By the way, if you are interested in this topic, this book has a nice chapter on it, as well as other kernel content. apress.com/9781430235361-4892 :D