内存映射文件和低内存情况

iOS平台在低内存情况下如何处理内存映射文件? 低内存的情况下,我的意思是当操作系统发送UIApplicationDidReceiveMemoryWarningNotification通知给应用程序中的所有观察者。

我们的文件被映射到内存使用+[NSData dataWithContentsOfMappedFile:] ,其文档的状态:

映射文件使用虚拟内存技术来避免将文件的页面复制到内存中,直到实际需要为止。

这是否意味着操作系统在不再使用的时候也会取消映射页面? 是否可以将页面标记为不再使用? 这个数据是只读的,如果这改变了场景。 如果我们直接使用mmap()呢? 这会更好吗?

内存映射文件一次将数据从磁盘复制到内存中。 除非使用mlock(2)连接到物理内存,否则未使用的页面可以自由换出,与其他任何虚拟内存相同。 内存映射留下了什么从磁盘复制到内存和什么时候到操作系统的决心。

从基础层面到BSD层面使用mmap不太可能产生太大的区别,除了使代码与其他基础代码的交互更加尴尬。

(这不是一个答案,但这将是有用的信息。)

从@ID_AA_Carmack tweet ,

@ID_AA_Carmack是iOS内存映射文件,在内存不足的情况下会自动取消映射吗? (使用+ [NSData dataWithContentsOfMappedFile]?)

ID_AA_Carmack为此回答,

@KhrobEdmonds是的,这是在iOS上使用映射文件的好处之一。 不过,我使用mmap()。

我不确定是否属实

从我的实验NSData不响应内存警告。 我testing通过创build一个内存映射的NSData和访问文件的一部分,以便它将被加载到内存,并最终发送内存警告。 内存警告后,内存使用量没有减less。 文档中没有提到内存会导致NSData在内存不足的情况下减less实际的内存使用,所以我相信它不会响应内存警告。 例如NSCache的文档说,它会尝试和玩的内存使用方面不错,加上我已经被告知它响应系统提出的低内存警告。

另外在我对iPod Touch(第四代)的简单testing中,我能够将大约600兆文件数据映射到虚拟内存使用+[NSData dataWithContentsOfMappedFile:] 。 接下来,我开始通过NSData实例的bytes属性来访问页面。 正如我所做的那样,真正的内存开始增长,但是它停止增长大约30兆的实际内存使用量。 所以它的实现方式似乎限制了多less真实的内存将被使用。

总之,如果你想减lessNSData对象的内存使用量,最好的办法是确保它们完全被释放,而不是依靠系统自动为你做的任何事情。

如果iOS和其他Unix一样 – 我敢打赌,就是在这方面–mmap()区域中的页面不会被“换出”。 他们只是简单地丢弃(如果他们是干净的)或写入底层文件,然后丢弃(如果他们是脏的)。 这个过程被称为“驱逐”页面。

由于您的内存映射是只读的,页面将始终是干净的。

内核将决定在物理内存变得紧张的情况下将哪些页面驱逐出去。

您可以使用posix_madvise()来提供内核提示,指出您希望哪些页面保持/驱逐。 特别是, POSIX_MADV_DONTNEED告诉内核随意驱逐页面; 或者如您所说,“将页面标记为不再使用”。

编写一些testing程序来查看iOS是否尊重“不需要”提示应该相当简单。 既然它是从BSD派生的,我敢打赌它会的。

用于文件备份内存的标准虚拟内存技术表示,操作系统可以随时随地丢弃页面,因为它可以在以后再次使用。 我还没有使用过iOS,但这已经是很长时间以来许多其他操作系统上虚拟内存的行为。

testing它的最简单的方法是将几个大文件映射到内存中,通读它们以确保将它们分页到内存中,并查看是否可以强制内存不足。 如果你不能,那么操作系统一旦确定它们不再被使用,就必须取消对这些页面的映射。

dataWithContentsOfMappedFile:方法现在已经从iOS5中弃用了。

使用mmap,因为您将避免这些情况。

Interesting Posts