我正在使用OpenGL ES开发2D iPhone游戏,并且我一直在达到24 MB的内存限制 - 我的应用程序一直在崩溃,错误代码为101.我试着很难找到内存的位置,但是仪器中的数字仍然比我预期的要大得多。
我使用Memory Monitor,Object Alloc,Leaks和OpenGL ES仪器运行应用程序。当应用程序加载时,自由物理内存从37 MB下降到23 MB,Object Alloc稳定在7 MB左右,Leaks显示两个或三个泄漏,几个字节大小,Gart对象大小约为5 MB,内存监视器说应用程序占用大约14 MB的实内存。令我感到困惑的是内存的去向 - 当我深入研究对象分配时,大部分内存都在纹理中,正如我所期望的那样。但我自己的纹理分配计数器和Gart对象大小都同意纹理应该占用大约5 MB。
我不知道分配任何其他值得一提的东西,并且Object Alloc同意。记忆在哪里? (如果这还不够,我会很乐意提供更多细节。)
更新:我真的试图找到可以分配如此多内存的地方,但没有结果。让我疯狂的是对象分配(~7 MB)与内存监视器(~14 MB)所示的实际内存使用之间的差异。即使存在巨大的泄漏或我忘记的大量内存,仍应出现在对象分配中,不应该出现吗?
我已经尝试了usual suspects,即。 UIImage
及其缓存,但没有帮助。有没有办法逐行跟踪内存使用情况“调试器样式”,观察每个语句对内存使用的影响?
到目前为止我发现了:
我真的我使用那么多内存。测量实际内存消耗并不容易,但经过大量计算后,我认为内存消耗真的很高。我的错。
我发现没有简单的方法来衡量使用的内存。内存监视器编号是准确的(这些是真正重要的数字),但内存监视器无法告诉您内存的确切位置。 Object Alloc工具几乎无法跟踪实际内存使用情况。当我创建一个纹理时,分配的内存计数器会上升一段时间(将纹理读入内存),然后下降(将纹理数据传递给OpenGL,释放)。这没关系,但并不总是发生 - 有时即使将纹理传递给OpenGL并从“我的”内存中释放出来,内存使用率也会保持很高。这意味着Object Alloc工具显示的内存总量小于实际总内存消耗量,但大于实际消耗减去纹理(real – textures < object alloc < real
)。去图。
我误读了编程指南。内存限制为24 MB适用于纹理和曲面,而不是整个应用程序。实际的红线位置更远,但我找不到任何硬数字。共识是25-30 MB是上限。
当系统内存不足时,会开始发送内存警告。我几乎没有什么可以免费的,但是其他应用程序确实会将一些内存释放回系统,特别是Safari(似乎是缓存网站)。当内存监视器中显示的可用内存为零时,系统开始查杀。
我不得不咬紧牙关并重写代码的某些部分以提高内存的效率,但我可能还在推动它。如果我要设计另一个游戏,我肯定会考虑一些资源分页。在当前的游戏中它非常难,因为事物一直处于运动中并且加载纹理会妨碍,即使在另一个线程中完成。 我会对其他人如何解决这个问题感兴趣。
请注意,这些只是我的观点,不一定非常准确。如果我发现有关此主题的更多内容,我会更新问题。如果理解这个问题的人会关心回答,我会保持问题公开,因为这些都比其他任何事情更具变通方法和猜测。
答案 0 :(得分:11)
我非常怀疑这是仪器中的一个错误。
首先,请阅读此blog post by Jeff Lamarche about openGL textures:
摘录:
纹理,即使它们是由它制成的 压缩图像,使用了很多你的 应用程序的内存堆因为它们 必须在记忆中扩大 用过的。每个像素占用四个字节, 所以忘了释放你的纹理 图像数据真的可以吃掉你的 记忆很快。
其次,可以使用Instruments调试纹理内存。有两种配置文件配置:OpenGL ES Analyzer和OpenGL ES Driver。您需要在设备上运行这些,因为模拟器不使用OpenGL。只需从XCode中选择Product-&gt; Profile,并在Instruments启动后查找这些配置文件。
有了这些知识,我就会这样做:
更新:在考虑了您的问题之后,我一直在阅读Apple's OpenGL ES Programming Guide并且它有非常好的信息。强烈推荐!
答案 1 :(得分:3)
一种方法是开始注释掉代码并检查错误是否仍然存在。是的,这是繁琐和基本的,但如果你知道错误的位置,它可能会有所帮助。
它崩溃的原因是它崩溃等等。
答案 2 :(得分:2)
嗯,这不是很多细节,但如果泄漏没有显示泄漏的位置,有两个重要的选择:
[i]泄漏错过了泄漏 [ii]记忆实际上并未泄露
修复[i]非常困难,但正如Eric Albert所说,向Apple提交错误报告会有所帮助。 [ii]意味着您正在使用的内存仍可在某处访问,但也许您已经忘记了它。是否有任何列表增长,而不丢弃旧条目?是否对realloc()进行了很多缓冲?答案 3 :(得分:2)
对于那些在2012年之后看到这一点的人:
真正加载到设备物理内存中的内存是VM Tracker Instrument中的Resident Memory。
分配工具仅标记由malloc / [NSObject alloc]和一些框架缓冲区创建的内存,例如,解压缩的图像位图不包含在分配工具中,但它总是占用大部分内存。
请观看WWDC 2012会话242 iOS应用程序性能:内存以获取Apple的信息。
答案 4 :(得分:0)
这对您没有特别的帮助,但如果您发现内存工具无法提供您需要的所有数据,请在bugreport.apple.com上提交错误。附上您的应用程序的副本以及工具如何不及您的分析的描述,Apple将看看他们是否可以改进工具。谢谢!