39

iOS平台在低内存场景下如何处理内存映射文件?低内存场景是指操作系统向UIApplicationDidReceiveMemoryWarningNotification应用程序中的所有观察者发送通知时。

我们的文件使用 映射到内存中+[NSData dataWithContentsOfMappedFile:],文档说明:

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

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

4

6 回答 6

20

内存映射文件一次将数据从磁盘复制到内存中一页。与任何其他虚拟内存一样,未使用的页面可以自由换出,除非它们已使用mlock(2). 内存映射决定了将什么从磁盘复制到内存以及何时复制到操作系统。

从 Foundation 级别降到 BSD 级别使用mmap不太可能有太大的不同,除了使必须与其他 Foundation 代码交互的代码有些尴尬之外。

于 2011-06-02T14:43:39.793 回答
11

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

来自@ID_AA_Carmack 推文

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

ID_AA_Carmack 对此进行了回复,

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

我不确定这是真的还是假的......

于 2011-06-08T04:14:01.543 回答
7

从我的实验 NSData 不响应内存警告。我通过创建内存映射的 NSData 并访问文件的某些部分进行测试,以便将其加载到内存中并最终发送内存警告。内存警告后内存使用量没有减少。文档中没有任何内容说内存会导致 NSData 在低内存情况下减少实际内存使用量,因此它让我相信它不会响应内存警告。例如,NSCache 文档说它会在内存使用方面尝试并表现得很好,而且我被告知它会响应系统引发的低内存警告。

同样在我对 iPod Touch(第 4 代)的简单测试中,我能够将大约 600 兆的文件数据映射到虚拟内存使用+[NSData dataWithContentsOfMappedFile:]中。接下来,我开始通过 NSData 实例上的 bytes 属性访问页面。当我这样做时,这个真实内存开始增长,但它在实际内存使用量约为 30 兆时停止增长。因此,它的实现方式似乎限制了将使用多少实际内存。

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

于 2011-06-07T18:49:50.290 回答
4

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

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

当物理内存紧张时,内核将决定驱逐哪些页面。

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

编写一些测试程序来查看 iOS 是否支持“不需要”提示应该非常简单。由于它是从 BSD 派生的,我敢打赌它会的。

于 2011-06-08T00:54:35.553 回答
1

文件支持内存的标准虚拟内存技术表明,操作系统可以随时随意丢弃页面,因为它总是可以稍后再次获取它们。我没有使用过 iOS,但很长一段时间以来,这一直是许多其他操作系统上虚拟内存的行为。

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

于 2011-06-02T13:55:24.903 回答
0

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

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

于 2012-04-03T01:52:01.063 回答