了解iPhone上的内存消耗

时间:2008-12-12 17:22:35

标签: iphone memory-management opengl-es

我正在使用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及其缓存,但没有帮助。有没有办法逐行跟踪内存使用情况“调试器样式”,观察每个语句对内存使用的影响?


到目前为止我发现了:

  1. 我真的使用那么多内存。测量实际内存消耗并不容易,但经过大量计算后,我认为内存消耗真的很高。我的错。

  2. 我发现没有简单的方法来衡量使用的内存。内存监视器编号是准确的(这些是真正重要的数字),但内存监视器无法告诉您内存的确切位置。 Object Alloc工具几乎无法跟踪实际内存使用情况。当我创建一个纹理时,分配的内存计数器会上升一段时间(将纹理读入内存),然后下降(将纹理数据传递给OpenGL,释放)。这没关系,但并不总是发生 - 有时即使将纹理传递给OpenGL并从“我的”内存中释放出来,内存使用率也会保持很高。这意味着Object Alloc工具显示的内存总量小于实际总内存消耗量,但大于实际消耗减去纹理(real – textures < object alloc < real)。去图。

  3. 我误读了编程指南。内存限制为24 MB适用于纹理和曲面,而不是整个应用程序。实际的红线位置更远,但我找不到任何硬数字。共识是25-30 MB是上限。

  4. 当系统内存不足时,会开始发送内存警告。我几乎没有什么可以免费的,但是其他应用程序确实会将一些内存释放回系统,特别是Safari(似乎是缓存网站)。当内存监视器中显示的可用内存为零时,系统开始查杀。

  5. 我不得不咬紧牙关并重写代码的某些部分以提高内存的效率,但我可能还在推动它。如果我要设计另一个游戏,我肯定会考虑一些资源分页。在当前的游戏中它非常难,因为事物一直处于运动中并且加载纹理会妨碍,即使在另一个线程中完成。 我会对其他人如何解决这个问题感兴趣。

    请注意,这些只是我的观点,不一定非常准确。如果我发现有关此主题的更多内容,我会更新问题。如果理解这个问题的人会关心回答,我会保持问题公开,因为这些都比其他任何事情更具变通方法和猜测。

5 个答案:

答案 0 :(得分:11)

我非常怀疑这是仪器中的一个错误。

首先,请阅读此blog post by Jeff Lamarche about openGL textures

  • 有一个如何加载的简单示例 纹理没有造成泄漏
  • 让我们了解“小” 图像,一旦加载就得到 进入openGL,实际上使用“很多”内存

摘录:

  

纹理,即使它们是由它制成的   压缩图像,使用了很多你的   应用程序的内存堆因为它们   必须在记忆中扩大   用过的。每个像素占用四个字节,   所以忘了释放你的纹理   图像数据真的可以吃掉你的   记忆很快。

其次,可以使用Instruments调试纹理内存。有两种配置文件配置:OpenGL ES AnalyzerOpenGL ES Driver。您需要在设备上运行这些,因为模拟器不使用OpenGL。只需从XCode中选择Product-&gt; Profile,并在Instruments启动后查找这些配置文件。


有了这些知识,我就会这样做:

  • 检查您是不是leaking memory - 这显然会导致此问题。
  • 确保你不是accessing autoreleased memory - 导致崩溃的常见原因。
  • 创建一个单独的测试应用程序,并单独(和组合)加载纹理,以找出导致问题的纹理(或其组合)。

更新:在考虑了您的问题之后,我一直在阅读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将看看他们是否可以改进工具。谢谢!