4

我们正在与 iPad 应用程序中的内存泄漏作斗争,该应用程序必须足够稳定才能保持 24/7 全天候运行,因此,内存泄漏是无法容忍的。

作为一个简单的测试,我们使用“Single View”模板创建了一个新的 iPad MonoTouch 项目,并使用 iPad 本身的 Instruments 执行它(iPad 3rd gen,没有其他应用程序在运行/在内存中)。

在 Instruments 中,如果我们经常点击“Mark Memory”按钮,它就会不断消耗内存。不多,但每隔一段时间就会有一点:

在此处输入图像描述

该应用程序实际上并没有对我们做任何事情,但显然正在执行一些分配内存的事情。

这是 iOS 问题、MonoTouch 问题还是其他问题?

创建 24/7 全天候 iPad 应用程序的计划是否现实?我们担心当我们开始添加代码时,内存泄漏量也会升级。显然,由于上图中的泄漏,该应用程序可以运行相当长一段时间,但如果它加速运行,内存满的截止日期将会更快。

4

1 回答 1

6

屏幕截图显示分配 - 不是内存泄漏。您可以要求 Instruments 跟踪泄漏,即没有找到对分配内存的引用。

但是,如果没有更多数据,就不可能说这些是否正常。我们至少需要知道分配来自哪里?Instruments 可以告诉您有关每个分配的更多详细信息。尝试向下钻取每个 heapshot 下的树,以查看分配的来源。

类似的情况通常是由于缓存造成的——这在每个级别都完成了。在应用程序代码之外,您会注意到 iOS 和它的框架进行缓存(例如图像、webkit ...)。

Mono 本身进行缓存,并且还使用在需要时会增长的内存池。将显示分配(即使已释放),但它不是泄漏 - 释放时,如果可能(例如大小),内存将被重用。

当然,它也可能是一个错误(在应用程序、任何框架、单点触控、iOS 中)。给定时间,如果应用程序发生在错误的位置(例如,运行循环的一部分、处理通知......),一个小的泄漏就足以使应用程序崩溃。只有找到分配的来源以及它们是否是重复分配(来自同一来源)才能告诉您这些分配的重要性。

编辑(更多)

所以昨晚我用自己的应用程序做了一个实验。下面的屏幕截图显示了 13 小时 45 分钟内的堆增长。

堆增长超过 13h45m

在前 4 小时 (1-13) 中,应用程序处于前台。最后一部分 (14) 应用程序在后台(晚上屏幕关闭)。记录在#14 之后也停止了,所以这个数字没有机会随着时间的推移而下降。

我的应用程序更大(初始基线为 5MB),启动后我没有使用它。一旦我知道初始化完成(它正在加载一个相当大的 80MB 数据库),我的第一个“标记堆”就完成了。OTOH 还监听网络事件,使用NSNetServiceBrowser回调到托管代码(没有任何视觉线索)。

展开 Heapshot #1 显示单个对象,48 字节,堆栈跟踪以_ZL13_cache_mallocm, cache_fill, lookupMethod, _class_lookupMethodAndLoadCache3... 结尾,在调用者中没有显示我的应用程序或单声道。

展开 Heapshot #2 显示了四个对象,前两个在其堆栈跟踪中带有CA::Render::Encoder::ObjectCacche::invalidate(...)和。CGNotificationCenterPostNotification第三个带有_cache_addForwardEntry,第四个看起来像 Heapshot #1 但是,就像第三个一样,它来自_XReceivedStatusBarDataAndAction(不是我的应用程序或 monotouch 直接完成的事情)。

展开 Heapshot #3 显示 10 个对象......列出它们有点长,但它们都在同一个_XReceivedStatusBarDataAndAction调用下。

扩展 heapshot #4 时的模式相同。

Heapshot #5 有一个区别(共 11 个),其中分配来自调度队列 (_xpc_connection_init),但没有可见的托管 (app) 或 mono[touch] 堆栈帧。

扩展堆 #6、#7、#8 时的模式相同(与 #3 相同)。

堆 #9 为空(未分配)。

Heapshot #10, #11 和 #3 一样。

Heapshot #12 也是空的。

Heapshot #13 与 #3 非常相似,但它也缓存相同的图像,并且在收到通知时发生CA::Render::Image::caches_encoding()另一个_cache_fill+ (不是托管的或下面的 MT 堆栈帧)。其他一些分配与通知有关。lookUpMethod_significantTimeChangeUIApplicationMain

Heapshot #14 主要是关于通知(可能被告知它将进入后台)。还有一些_cache_fill分配。

这是 iOS 问题、MonoTouch 问题还是其他问题?

上面没有任何内容指向 MonoTouch 甚至我的应用程序。OTOH 我没有将它与 ObjC 应用程序进行比较(可能没有时间这样做),但我相信你会看到一些非常接近的东西 - 取决于正在使用的 API/服务(并且执行相同操作的应用程序应该显示相同)分配)。

就像我在 YMMV 之前所说的那样,泄漏(或意外的内存保留)通常是特定于 API 的。如果您在仪器会话中发现奇怪的堆栈跟踪,请填写关于它们的错误报告(给 Xamarin 或 Apple,取决于堆栈跟踪),以便可以分析和修复它们(如果有错误)。

创建 24/7 全天候 iPad 应用程序的计划是否现实?

至于 24/7 运行应用程序,我认为它可以完成 - 但它需要用户的合作(这可能是不现实的)。切换到另一个应用程序(主页按钮、手势)意味着您的应用程序不会在前台,Apple 可以终止任何后台应用程序以回收内存。例如,App X 内存不足,iOS 开始询问,然后杀死后台应用程序以满足前台应用程序。

于 2013-01-06T01:20:57.683 回答