在低内存情况下,iOS平台如何处理内存映射文件?在低内存情况下,我的意思是操作系统向应用程序中的所有观察者发送UIApplicationDidReceiveMemoryWarningNotification
通知。
我们的文件使用+[NSData dataWithContentsOfMappedFile:]
映射到内存中,文档的状态为:
映射文件使用虚拟内存技术来避免将文件页面复制到内存中,直到实际需要它们为止。
这是否意味着操作系统还会在页面不再使用时取消映射?是否可以将页面标记为不再使用?如果更改方案,则此数据是只读的。如果我们直接使用mmap()
怎么样?这会更好吗?
答案 0 :(得分:19)
内存映射文件一次将数据从磁盘复制到内存中。未使用的页面可以自由换出,与任何其他虚拟内存相同,除非它们已使用mlock(2)
连接到物理内存。内存映射会确定从磁盘复制到内存的内容以及何时复制到操作系统。
从基础级别降级到BSD级别以使用mmap
不太可能产生太大的影响,除了使必须与其他基础代码接口的代码更加尴尬之外。
答案 1 :(得分:10)
(这不是一个答案,但它将是有用的信息。)
@ID_AA_Carmack是iOS内存映射文件在低内存条件下自动取消映射? (使用+ [NSData dataWithContentsOfMappedFile]?)
ID_AA_Carmack回复此事,
@KhrobEdmonds是的,这是在iOS上使用映射文件的一大好处。不过我使用mmap()。
我不确定这是不是真的......
答案 2 :(得分:7)
从我的实验中,NSData不响应内存警告。我通过创建一个内存映射的NSData并访问文件的一部分进行测试,以便将其加载到内存中并最终发送内存警告。内存警告后内存使用量没有减少。文档中没有任何内容表明内存会导致NSData在低内存情况下减少实际内存使用量,因此它让我相信它不响应内存警告。例如,NSCache文档说它会尝试在内存使用方面发挥出色,而且我被告知它会响应系统引发的低内存警告。
同样在我对iPod Touch(第4代)的简单测试中,我能够将大约600兆的文件数据映射到虚拟内存使用+[NSData dataWithContentsOfMappedFile:]
。接下来,我开始通过NSData实例上的bytes属性访问页面。正如我所做的那样,真正的内存开始增长,然而它停止增长大约30兆的实际内存使用量。因此,它的实现方式似乎限制了将使用多少实内存。
简而言之,如果你想减少NSData对象的内存使用量,最好的办法是确保它们完全释放,而不是依赖系统代表你自动完成的任何事情。
答案 3 :(得分:4)
如果iOS就像任何其他Unix一样 - 我敢打赌钱就是这样 - mmap()区域中的页面不会被“换出”;它们只是被删除(如果它们是干净的)或被写入底层文件然后丢弃(如果它们是脏的)。此过程称为“逐出”页面。
由于您的内存映射是只读的,因此页面将始终保持干净。
当物理内存变紧时,内核将决定逐出哪些页面。
您可以使用posix_madvise()向内核提示您希望保留/退出哪些页面。特别是,POSIX_MADV_DONTNEED
告诉内核可以自由地逐出页面;或者如您所说,“将页面标记为不再使用”。
编写一些测试程序以查看iOS是否尊重“不需要”提示应该非常简单。既然它来自BSD,我打赌它会。
答案 4 :(得分:1)
文件支持内存的标准虚拟内存技术表明操作系统可以随时丢弃页面,因为它总是可以在以后再次获取它们。我没有使用iOS,但这已经成为许多其他操作系统上虚拟内存的行为很长一段时间了。
测试它的最简单方法是将几个大文件映射到内存中,读取它们以确保它将它们分页到内存中,并查看是否可以强制执行低内存情况。如果你不能,那么一旦确定它们不再使用,操作系统必须取消映射页面。
答案 5 :(得分:0)
现在,iOS5已弃用dataWithContentsOfMappedFile:
方法。
使用mmap,因为您将避免这些情况。