I am working on a 2D iPhone game using OpenGL ES and I keep hitting the 24 MB memory limit – my application keeps crashing with the error code 101. I tried real hard to find where the memory goes, but the numbers in Instruments are still much bigger than what I would expect.
我正在使用OpenGL ES开发2D iPhone游戏,并且我一直在达到24 MB的内存限制 - 我的应用程序一直在崩溃,错误代码为101.我真的很难找到内存的位置,但是仪器中的数字仍然很多大于我的预期。
I ran the application with the Memory Monitor, Object Alloc, Leaks and OpenGL ES instruments. When the application gets loaded, free physical memory drops from 37 MB to 23 MB, the Object Alloc settles around 7 MB, Leaks show two or three leaks a few bytes in size, the Gart Object Size is about 5 MB and Memory Monitor says the application takes up about 14 MB of real memory. I am perplexed as where did the memory go – when I dig into the Object Allocations, most of the memory is in the textures, exactly as I would expect. But both my own texture allocation counter and the Gart Object Size agree that the textures should take up somewhere around 5 MB.
我使用Memory Monitor,Object Alloc,Leaks和OpenGL ES仪器运行应用程序。当应用程序加载时,*物理内存从37 MB下降到23 MB,Object Alloc稳定在7 MB左右,Leaks显示两个或三个泄漏,大小为几个字节,Gart对象大小约为5 MB,内存监视器说应用程序占用大约14 MB的实内存。令我感到困惑的是内存的去向 - 当我深入研究对象分配时,大部分内存都在纹理中,正如我所期望的那样。但是我自己的纹理分配计数器和Gart对象大小都同意纹理应占用大约5 MB。
I am not aware of allocating anything else that would be worth mentioning, and the Object Alloc agrees. Where does the memory go? (I would be glad to supply more details if this is not enough.)
我不知道分配任何其他值得一提的东西,并且Object Alloc同意。记忆在哪里? (如果这还不够,我会很乐意提供更多细节。)
Update: I really tried to find where I could allocate so much memory, but with no results. What drives me wild is the difference between the Object Allocations (~7 MB) and real memory usage as shown by Memory Monitor (~14 MB). Even if there were huge leaks or huge chunks of memory I forget about, the should still show up in the Object Allocations, shouldn’t they?
更新:我真的试图找到我可以分配这么多内存的地方,但没有结果。让我疯狂的是对象分配(~7 MB)与内存监视器(~14 MB)所示的实际内存使用之间的差异。即使我忘记了巨大的泄漏或巨大的内存块,它仍应出现在对象分配中,不应该出现吗?
I’ve already tried the usual suspects, ie. the UIImage
with its caching, but that did not help. Is there a way to track memory usage “debugger-style”, line by line, watching each statement’s impact on memory usage?
我已经尝试过通常的嫌疑人,即。 UIImage的缓存,但没有帮助。有没有办法逐行跟踪内存使用情况“调试器样式”,观察每个语句对内存使用情况的影响?
What I have found so far:
到目前为止我发现了什么:
-
I really am using that much memory. It is not easy to measure the real memory consumption, but after a lot of counting I think the memory consumption is really that high. My fault.
我真的在使用那么多记忆。测量实际内存消耗并不容易,但经过大量计算后,我认为内存消耗确实很高。我的错。
-
I found no easy way to measure the memory used. The Memory Monitor numbers are accurate (these are the numbers that really matter), but the Memory Monitor can’t tell you where exactly the memory goes. The Object Alloc tool is almost useless for tracking the real memory usage. When I create a texture, the allocated memory counter goes up for a while (reading the texture into the memory), then drops (passing the texture data to OpenGL, freeing). This is OK, but does not always happen – sometimes the memory usage stays high even after the texture has been passed on to OpenGL and freed from “my” memory. This means that the total amount of memory allocated as shown by the Object Alloc tool is smaller than the real total memory consumption, but bigger than the real consumption minus textures (
real – textures < object alloc < real
). Go figure.我发现没有简单的方法来衡量使用的内存。内存监视器编号是准确的(这些是真正重要的数字),但内存监视器无法告诉您内存的确切位置。 Object Alloc工具几乎无法跟踪实际内存使用情况。当我创建一个纹理时,分配的内存计数器会上升一段时间(将纹理读入内存),然后下降(将纹理数据传递给OpenGL,释放)。这没关系,但并不总是发生 - 有时即使纹理传递给OpenGL并从“我的”内存中释放出来,内存使用率也会保持很高。这意味着Object Alloc工具所显示的内存总量小于实际总内存消耗量,但大于实际消耗减去纹理(实际纹理
-
I misread the Programming Guide. The memory limit of 24 MB applies to textures and surfaces, not the whole application. The actual red line lies a bit further, but I could not find any hard numbers. The consensus is that 25–30 MB is the ceiling.
我误读了编程指南。内存限制为24 MB适用于纹理和曲面,而不是整个应用程序。实际的红线有点进一步,但我找不到任何硬数字。共识是25-30 MB是上限。
-
When the system gets short on memory, it starts sending the memory warning. I have almost nothing to free, but other applications do release some memory back to the system, especially Safari (which seems to be caching the websites). When the free memory as shown in the Memory Monitor goes zero, the system starts killing.
当系统内存不足时,它会开始发送内存警告。我几乎没有什么可以免费的,但其他应用程序确实会释放一些内存回系统,特别是Safari(似乎是缓存网站)。当内存监视器中显示的可用内存为零时,系统开始查杀。
I had to bite the bullet and rewrite some parts of the code to be more efficient on memory, but I am probably still pushing it. If I were to design another game, I would certainly think of some resource paging. With the current game it’s quite hard, because the thing is in motion all the time and loading the textures gets in the way, even if done in another thread. I would be much interested in how other people solve this issue.
我不得不咬紧牙关并重写代码的某些部分以提高内存的效率,但我可能还在推动它。如果我要设计另一个游戏,我肯定会考虑一些资源分页。在当前的游戏中它非常难,因为事物一直处于运动中并且加载纹理会妨碍,即使在另一个线程中完成。我会对其他人如何解决这个问题感兴趣。
Please note that these are just my views that do not have to be much accurate. If I find out something more to say on this topic, I will update the question. I’ll keep the question open in case somebody who understands the issue would care to answer, since these all are more workarounds and guesses than anything else.
请注意,这些只是我的观点,不一定非常准确。如果我发现有关此主题的更多内容,我会更新问题。如果理解这个问题的人会关心回答,我会保持问题公开,因为这些都是比其他任何事情更多的变通办法和猜测。
5 个解决方案
#1
11
I highly doubt this is a bug in Instruments.
我非常怀疑这是仪器中的一个错误。
First, read this blog post by Jeff Lamarche about openGL textures:
首先,阅读Jeff Lamarche关于openGL纹理的博客文章:
- has a simple example of how to load textures without causing leaks
- 有一个简单的例子,说明如何加载纹理而不会导致泄漏
- gives understanding of how "small" images, get once they are loaded into openGL, actually use "a lot" of memory
- 让我们了解“小”图像,一旦加载到openGL中,实际上会使用“很多”内存
Excerpt:
摘抄:
Textures, even if they're made from compressed images, use a lot of your application's memory heap because they have to be expanded in memory to be used. Every pixel takes up four bytes, so forgetting to release your texture image data can really eat up your memory quickly.
纹理,即使它们是由压缩图像构成的,也会使用大量应用程序的内存堆,因为它们必须在内存中进行扩展才能使用。每个像素占用四个字节,因此忘记释放纹理图像数据可能会很快耗尽您的记忆。
Second, it is possible to debug texture memory with Instruments. There are two profiling configurations: OpenGL ES Analyzer and OpenGL ES Driver. You will need to run these on the device, as the simulator doesn't use OpenGL. Simply choose Product->Profile from XCode and look for these profiles once Instruments launches.
其次,可以使用Instruments调试纹理存储器。有两种配置文件配置:OpenGL ES Analyzer和OpenGL ES Driver。您需要在设备上运行这些,因为模拟器不使用OpenGL。只需从XCode中选择Product-> Profile,并在Instruments启动后查找这些配置文件。
Armed with that knowledge, here is what I would do:
有了这些知识,这就是我要做的:
- Check that you're not leaking memory -- this will obviously cause this problem.
- 检查您是否没有泄漏内存 - 这显然会导致此问题。
- Ensure your'e not accessing autoreleased memory -- common cause of crashes.
- 确保您不能访问自动释放的内存 - 导致崩溃的常见原因。
- Create a separate test app and play with loading textures individually (and in combination) to find out what texture (or combination thereof) is causing the problem.
- 创建一个单独的测试应用程序,并单独(和组合)加载纹理,以找出导致问题的纹理(或其组合)。
UPDATE: After thinking about your question, I've been reading Apple's OpenGL ES Programming Guide and it has very good information. Highly recommended!
更新:在考虑了你的问题后,我一直在阅读Apple的OpenGL ES编程指南,它有非常好的信息。强烈推荐!
#2
3
One way is to start commenting out code and checking to see if the bug still happens. Yes it is tedious and elementary, but it might help if you knew where the bug was.
一种方法是开始注释掉代码并检查错误是否仍然发生。是的,这是繁琐和基本的,但如果你知道bug在哪里可能会有所帮助。
Where it is crashing is why it is crashing, etc.
它崩溃的地方就是为什么它会崩溃等等。
#3
2
Hrmm, that's not many details, but if leaks doesn't show you where the leaks are, there are two important options:
嗯,这不是很多细节,但如果泄漏没有显示泄漏的位置,有两个重要的选择:
[i] Leaks missed a leak [ii] The memory isn't actually being leaked
[i]泄漏错过了泄漏[ii]记忆实际上并未泄露
fixing [i] is quite hard, but as Eric Albert said filing a bug report with Apple will help. [ii] means that the memory you're using is still accessible somewhere, but perhaps you've forgotten about it. Are any lists growing, without throwing out old entries? Are any buffers being realloc()ed a lot?
修复[i]非常困难,但正如Eric Albert所说,向Apple提交错误报告会有所帮助。 [ii]意味着您正在使用的内存仍可在某处访问,但也许您已经忘记了它。是否有任何列表增长,而没有丢失旧条目?是否对realloc()进行了很多缓冲?
#4
2
For those seeing this after the year 2012:
对于那些在2012年之后看到这个的人:
The memory really loaded into device's physical memory is the Resident Memory in VM Tracker Instrument.
真正加载到设备物理内存中的内存是VM Tracker Instrument中的Resident Memory。
Allocation Instrument only marks the memory created by malloc/[NSObject alloc] and some framework buffer, for example, decompressed image bitmap is not included in Allocation Instrument but it always takes most of your memory.
分配工具仅标记由malloc / [NSObject alloc]和一些框架缓冲区创建的内存,例如,解压缩的图像位图不包含在分配工具中,但它总是占用大部分内存。
Please Watch WWDC 2012 Session 242 iOS App Performance: Memory to get the information from Apple.
请观看WWDC 2012 Session 242 iOS应用程序性能:内存以获取Apple提供的信息。
#5
0
This doesn't specifically help you, but if you find that the memory tools don't provide all the data you need, please file a bug at bugreport.apple.com. Attach a copy of your app and a description of how the tools are falling short of your analysis and Apple will see if they can improve the tools. Thanks!
这对您没有特别的帮助,但如果您发现内存工具无法提供您需要的所有数据,请在bugreport.apple.com上提交错误。附上您的应用程序的副本以及工具如何不及您的分析的描述,Apple将看看他们是否可以改进工具。谢谢!
#1
11
I highly doubt this is a bug in Instruments.
我非常怀疑这是仪器中的一个错误。
First, read this blog post by Jeff Lamarche about openGL textures:
首先,阅读Jeff Lamarche关于openGL纹理的博客文章:
- has a simple example of how to load textures without causing leaks
- 有一个简单的例子,说明如何加载纹理而不会导致泄漏
- gives understanding of how "small" images, get once they are loaded into openGL, actually use "a lot" of memory
- 让我们了解“小”图像,一旦加载到openGL中,实际上会使用“很多”内存
Excerpt:
摘抄:
Textures, even if they're made from compressed images, use a lot of your application's memory heap because they have to be expanded in memory to be used. Every pixel takes up four bytes, so forgetting to release your texture image data can really eat up your memory quickly.
纹理,即使它们是由压缩图像构成的,也会使用大量应用程序的内存堆,因为它们必须在内存中进行扩展才能使用。每个像素占用四个字节,因此忘记释放纹理图像数据可能会很快耗尽您的记忆。
Second, it is possible to debug texture memory with Instruments. There are two profiling configurations: OpenGL ES Analyzer and OpenGL ES Driver. You will need to run these on the device, as the simulator doesn't use OpenGL. Simply choose Product->Profile from XCode and look for these profiles once Instruments launches.
其次,可以使用Instruments调试纹理存储器。有两种配置文件配置:OpenGL ES Analyzer和OpenGL ES Driver。您需要在设备上运行这些,因为模拟器不使用OpenGL。只需从XCode中选择Product-> Profile,并在Instruments启动后查找这些配置文件。
Armed with that knowledge, here is what I would do:
有了这些知识,这就是我要做的:
- Check that you're not leaking memory -- this will obviously cause this problem.
- 检查您是否没有泄漏内存 - 这显然会导致此问题。
- Ensure your'e not accessing autoreleased memory -- common cause of crashes.
- 确保您不能访问自动释放的内存 - 导致崩溃的常见原因。
- Create a separate test app and play with loading textures individually (and in combination) to find out what texture (or combination thereof) is causing the problem.
- 创建一个单独的测试应用程序,并单独(和组合)加载纹理,以找出导致问题的纹理(或其组合)。
UPDATE: After thinking about your question, I've been reading Apple's OpenGL ES Programming Guide and it has very good information. Highly recommended!
更新:在考虑了你的问题后,我一直在阅读Apple的OpenGL ES编程指南,它有非常好的信息。强烈推荐!
#2
3
One way is to start commenting out code and checking to see if the bug still happens. Yes it is tedious and elementary, but it might help if you knew where the bug was.
一种方法是开始注释掉代码并检查错误是否仍然发生。是的,这是繁琐和基本的,但如果你知道bug在哪里可能会有所帮助。
Where it is crashing is why it is crashing, etc.
它崩溃的地方就是为什么它会崩溃等等。
#3
2
Hrmm, that's not many details, but if leaks doesn't show you where the leaks are, there are two important options:
嗯,这不是很多细节,但如果泄漏没有显示泄漏的位置,有两个重要的选择:
[i] Leaks missed a leak [ii] The memory isn't actually being leaked
[i]泄漏错过了泄漏[ii]记忆实际上并未泄露
fixing [i] is quite hard, but as Eric Albert said filing a bug report with Apple will help. [ii] means that the memory you're using is still accessible somewhere, but perhaps you've forgotten about it. Are any lists growing, without throwing out old entries? Are any buffers being realloc()ed a lot?
修复[i]非常困难,但正如Eric Albert所说,向Apple提交错误报告会有所帮助。 [ii]意味着您正在使用的内存仍可在某处访问,但也许您已经忘记了它。是否有任何列表增长,而没有丢失旧条目?是否对realloc()进行了很多缓冲?
#4
2
For those seeing this after the year 2012:
对于那些在2012年之后看到这个的人:
The memory really loaded into device's physical memory is the Resident Memory in VM Tracker Instrument.
真正加载到设备物理内存中的内存是VM Tracker Instrument中的Resident Memory。
Allocation Instrument only marks the memory created by malloc/[NSObject alloc] and some framework buffer, for example, decompressed image bitmap is not included in Allocation Instrument but it always takes most of your memory.
分配工具仅标记由malloc / [NSObject alloc]和一些框架缓冲区创建的内存,例如,解压缩的图像位图不包含在分配工具中,但它总是占用大部分内存。
Please Watch WWDC 2012 Session 242 iOS App Performance: Memory to get the information from Apple.
请观看WWDC 2012 Session 242 iOS应用程序性能:内存以获取Apple提供的信息。
#5
0
This doesn't specifically help you, but if you find that the memory tools don't provide all the data you need, please file a bug at bugreport.apple.com. Attach a copy of your app and a description of how the tools are falling short of your analysis and Apple will see if they can improve the tools. Thanks!
这对您没有特别的帮助,但如果您发现内存工具无法提供您需要的所有数据,请在bugreport.apple.com上提交错误。附上您的应用程序的副本以及工具如何不及您的分析的描述,Apple将看看他们是否可以改进工具。谢谢!